diff --git a/API/api.py b/API/api.py new file mode 100644 index 0000000..9f75567 --- /dev/null +++ b/API/api.py @@ -0,0 +1,7 @@ +import requests + +for i in range(5): + url = "https://dog.ceo/api/breeds/image/random" + response = requests.get(url) + data = response.json() + print(data["message"]) \ No newline at end of file diff --git a/README.md b/README.md index d63b08f..72cd144 100644 --- a/README.md +++ b/README.md @@ -127,6 +127,8 @@ playwright install Run the bootstrap script (signup → login → save session): ```bash python scripts/bootstrap_signup.py --name "Jane Doe" --email "jane@example.com" --password "StrongPass123" --storage "auth/storage_state.json" +```bash +python -m scripts.bootstrap_signup --name "Jane Doe" --email "test@example.com" --password "StrongPass123" --storage "auth/storage_state.json" ``` This will: - Open the demo **Sign Up** page (`/signup.html`) @@ -300,3 +302,5 @@ pytest -vv --html=reports/html/report.html --self-contained-html --- 🎉 You’re all set — the framework signs up, logs in, saves the session, and reuses it for fast, reliable tests. + +Watson Testing here :) \ No newline at end of file diff --git a/node_modules/.bin/acorn b/node_modules/.bin/acorn new file mode 120000 index 0000000..679bd16 --- /dev/null +++ b/node_modules/.bin/acorn @@ -0,0 +1,16 @@ +#!/bin/sh +basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')") + +case `uname` in + *CYGWIN*|*MINGW*|*MSYS*) + if command -v cygpath > /dev/null 2>&1; then + basedir=`cygpath -w "$basedir"` + fi + ;; +esac + +if [ -x "$basedir/node" ]; then + exec "$basedir/node" "$basedir/../acorn/bin/acorn" "$@" +else + exec node "$basedir/../acorn/bin/acorn" "$@" +fi diff --git a/node_modules/.bin/acorn.cmd b/node_modules/.bin/acorn.cmd new file mode 100644 index 0000000..a9324df --- /dev/null +++ b/node_modules/.bin/acorn.cmd @@ -0,0 +1,17 @@ +@ECHO off +GOTO start +:find_dp0 +SET dp0=%~dp0 +EXIT /b +:start +SETLOCAL +CALL :find_dp0 + +IF EXIST "%dp0%\node.exe" ( + SET "_prog=%dp0%\node.exe" +) ELSE ( + SET "_prog=node" + SET PATHEXT=%PATHEXT:;.JS;=;% +) + +endLocal & goto #_undefined_# 2>NUL || title %COMSPEC% & "%_prog%" "%dp0%\..\acorn\bin\acorn" %* diff --git a/node_modules/.bin/acorn.ps1 b/node_modules/.bin/acorn.ps1 new file mode 100644 index 0000000..6f6dcdd --- /dev/null +++ b/node_modules/.bin/acorn.ps1 @@ -0,0 +1,28 @@ +#!/usr/bin/env pwsh +$basedir=Split-Path $MyInvocation.MyCommand.Definition -Parent + +$exe="" +if ($PSVersionTable.PSVersion -lt "6.0" -or $IsWindows) { + # Fix case when both the Windows and Linux builds of Node + # are installed in the same directory + $exe=".exe" +} +$ret=0 +if (Test-Path "$basedir/node$exe") { + # Support pipeline input + if ($MyInvocation.ExpectingInput) { + $input | & "$basedir/node$exe" "$basedir/../acorn/bin/acorn" $args + } else { + & "$basedir/node$exe" "$basedir/../acorn/bin/acorn" $args + } + $ret=$LASTEXITCODE +} else { + # Support pipeline input + if ($MyInvocation.ExpectingInput) { + $input | & "node$exe" "$basedir/../acorn/bin/acorn" $args + } else { + & "node$exe" "$basedir/../acorn/bin/acorn" $args + } + $ret=$LASTEXITCODE +} +exit $ret diff --git a/node_modules/.bin/mcr b/node_modules/.bin/mcr new file mode 120000 index 0000000..01215d7 --- /dev/null +++ b/node_modules/.bin/mcr @@ -0,0 +1,16 @@ +#!/bin/sh +basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')") + +case `uname` in + *CYGWIN*|*MINGW*|*MSYS*) + if command -v cygpath > /dev/null 2>&1; then + basedir=`cygpath -w "$basedir"` + fi + ;; +esac + +if [ -x "$basedir/node" ]; then + exec "$basedir/node" "$basedir/../monocart-coverage-reports/lib/cli.js" "$@" +else + exec node "$basedir/../monocart-coverage-reports/lib/cli.js" "$@" +fi diff --git a/node_modules/.bin/mcr.cmd b/node_modules/.bin/mcr.cmd new file mode 100644 index 0000000..a70bab6 --- /dev/null +++ b/node_modules/.bin/mcr.cmd @@ -0,0 +1,17 @@ +@ECHO off +GOTO start +:find_dp0 +SET dp0=%~dp0 +EXIT /b +:start +SETLOCAL +CALL :find_dp0 + +IF EXIST "%dp0%\node.exe" ( + SET "_prog=%dp0%\node.exe" +) ELSE ( + SET "_prog=node" + SET PATHEXT=%PATHEXT:;.JS;=;% +) + +endLocal & goto #_undefined_# 2>NUL || title %COMSPEC% & "%_prog%" "%dp0%\..\monocart-coverage-reports\lib\cli.js" %* diff --git a/node_modules/.bin/mcr.ps1 b/node_modules/.bin/mcr.ps1 new file mode 100644 index 0000000..0b58a0d --- /dev/null +++ b/node_modules/.bin/mcr.ps1 @@ -0,0 +1,28 @@ +#!/usr/bin/env pwsh +$basedir=Split-Path $MyInvocation.MyCommand.Definition -Parent + +$exe="" +if ($PSVersionTable.PSVersion -lt "6.0" -or $IsWindows) { + # Fix case when both the Windows and Linux builds of Node + # are installed in the same directory + $exe=".exe" +} +$ret=0 +if (Test-Path "$basedir/node$exe") { + # Support pipeline input + if ($MyInvocation.ExpectingInput) { + $input | & "$basedir/node$exe" "$basedir/../monocart-coverage-reports/lib/cli.js" $args + } else { + & "$basedir/node$exe" "$basedir/../monocart-coverage-reports/lib/cli.js" $args + } + $ret=$LASTEXITCODE +} else { + # Support pipeline input + if ($MyInvocation.ExpectingInput) { + $input | & "node$exe" "$basedir/../monocart-coverage-reports/lib/cli.js" $args + } else { + & "node$exe" "$basedir/../monocart-coverage-reports/lib/cli.js" $args + } + $ret=$LASTEXITCODE +} +exit $ret diff --git a/node_modules/.bin/node-which b/node_modules/.bin/node-which new file mode 120000 index 0000000..b49b03f --- /dev/null +++ b/node_modules/.bin/node-which @@ -0,0 +1,16 @@ +#!/bin/sh +basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')") + +case `uname` in + *CYGWIN*|*MINGW*|*MSYS*) + if command -v cygpath > /dev/null 2>&1; then + basedir=`cygpath -w "$basedir"` + fi + ;; +esac + +if [ -x "$basedir/node" ]; then + exec "$basedir/node" "$basedir/../which/bin/node-which" "$@" +else + exec node "$basedir/../which/bin/node-which" "$@" +fi diff --git a/node_modules/.bin/node-which.cmd b/node_modules/.bin/node-which.cmd new file mode 100644 index 0000000..8738aed --- /dev/null +++ b/node_modules/.bin/node-which.cmd @@ -0,0 +1,17 @@ +@ECHO off +GOTO start +:find_dp0 +SET dp0=%~dp0 +EXIT /b +:start +SETLOCAL +CALL :find_dp0 + +IF EXIST "%dp0%\node.exe" ( + SET "_prog=%dp0%\node.exe" +) ELSE ( + SET "_prog=node" + SET PATHEXT=%PATHEXT:;.JS;=;% +) + +endLocal & goto #_undefined_# 2>NUL || title %COMSPEC% & "%_prog%" "%dp0%\..\which\bin\node-which" %* diff --git a/node_modules/.bin/node-which.ps1 b/node_modules/.bin/node-which.ps1 new file mode 100644 index 0000000..cfb09e8 --- /dev/null +++ b/node_modules/.bin/node-which.ps1 @@ -0,0 +1,28 @@ +#!/usr/bin/env pwsh +$basedir=Split-Path $MyInvocation.MyCommand.Definition -Parent + +$exe="" +if ($PSVersionTable.PSVersion -lt "6.0" -or $IsWindows) { + # Fix case when both the Windows and Linux builds of Node + # are installed in the same directory + $exe=".exe" +} +$ret=0 +if (Test-Path "$basedir/node$exe") { + # Support pipeline input + if ($MyInvocation.ExpectingInput) { + $input | & "$basedir/node$exe" "$basedir/../which/bin/node-which" $args + } else { + & "$basedir/node$exe" "$basedir/../which/bin/node-which" $args + } + $ret=$LASTEXITCODE +} else { + # Support pipeline input + if ($MyInvocation.ExpectingInput) { + $input | & "node$exe" "$basedir/../which/bin/node-which" $args + } else { + & "node$exe" "$basedir/../which/bin/node-which" $args + } + $ret=$LASTEXITCODE +} +exit $ret diff --git a/node_modules/.bin/playwright b/node_modules/.bin/playwright new file mode 100644 index 0000000..8e4988e --- /dev/null +++ b/node_modules/.bin/playwright @@ -0,0 +1,16 @@ +#!/bin/sh +basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')") + +case `uname` in + *CYGWIN*|*MINGW*|*MSYS*) + if command -v cygpath > /dev/null 2>&1; then + basedir=`cygpath -w "$basedir"` + fi + ;; +esac + +if [ -x "$basedir/node" ]; then + exec "$basedir/node" "$basedir/../@playwright/test/cli.js" "$@" +else + exec node "$basedir/../@playwright/test/cli.js" "$@" +fi diff --git a/node_modules/.bin/playwright-core b/node_modules/.bin/playwright-core new file mode 100644 index 0000000..bc2c5c8 --- /dev/null +++ b/node_modules/.bin/playwright-core @@ -0,0 +1,16 @@ +#!/bin/sh +basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')") + +case `uname` in + *CYGWIN*|*MINGW*|*MSYS*) + if command -v cygpath > /dev/null 2>&1; then + basedir=`cygpath -w "$basedir"` + fi + ;; +esac + +if [ -x "$basedir/node" ]; then + exec "$basedir/node" "$basedir/../playwright-core/cli.js" "$@" +else + exec node "$basedir/../playwright-core/cli.js" "$@" +fi diff --git a/node_modules/.bin/playwright-core.cmd b/node_modules/.bin/playwright-core.cmd new file mode 100644 index 0000000..1128204 --- /dev/null +++ b/node_modules/.bin/playwright-core.cmd @@ -0,0 +1,17 @@ +@ECHO off +GOTO start +:find_dp0 +SET dp0=%~dp0 +EXIT /b +:start +SETLOCAL +CALL :find_dp0 + +IF EXIST "%dp0%\node.exe" ( + SET "_prog=%dp0%\node.exe" +) ELSE ( + SET "_prog=node" + SET PATHEXT=%PATHEXT:;.JS;=;% +) + +endLocal & goto #_undefined_# 2>NUL || title %COMSPEC% & "%_prog%" "%dp0%\..\playwright-core\cli.js" %* diff --git a/node_modules/.bin/playwright-core.ps1 b/node_modules/.bin/playwright-core.ps1 new file mode 100644 index 0000000..e914b99 --- /dev/null +++ b/node_modules/.bin/playwright-core.ps1 @@ -0,0 +1,28 @@ +#!/usr/bin/env pwsh +$basedir=Split-Path $MyInvocation.MyCommand.Definition -Parent + +$exe="" +if ($PSVersionTable.PSVersion -lt "6.0" -or $IsWindows) { + # Fix case when both the Windows and Linux builds of Node + # are installed in the same directory + $exe=".exe" +} +$ret=0 +if (Test-Path "$basedir/node$exe") { + # Support pipeline input + if ($MyInvocation.ExpectingInput) { + $input | & "$basedir/node$exe" "$basedir/../playwright-core/cli.js" $args + } else { + & "$basedir/node$exe" "$basedir/../playwright-core/cli.js" $args + } + $ret=$LASTEXITCODE +} else { + # Support pipeline input + if ($MyInvocation.ExpectingInput) { + $input | & "node$exe" "$basedir/../playwright-core/cli.js" $args + } else { + & "node$exe" "$basedir/../playwright-core/cli.js" $args + } + $ret=$LASTEXITCODE +} +exit $ret diff --git a/node_modules/.bin/playwright.cmd b/node_modules/.bin/playwright.cmd new file mode 100644 index 0000000..ab9fe6a --- /dev/null +++ b/node_modules/.bin/playwright.cmd @@ -0,0 +1,17 @@ +@ECHO off +GOTO start +:find_dp0 +SET dp0=%~dp0 +EXIT /b +:start +SETLOCAL +CALL :find_dp0 + +IF EXIST "%dp0%\node.exe" ( + SET "_prog=%dp0%\node.exe" +) ELSE ( + SET "_prog=node" + SET PATHEXT=%PATHEXT:;.JS;=;% +) + +endLocal & goto #_undefined_# 2>NUL || title %COMSPEC% & "%_prog%" "%dp0%\..\@playwright\test\cli.js" %* diff --git a/node_modules/.bin/playwright.ps1 b/node_modules/.bin/playwright.ps1 new file mode 100644 index 0000000..ccb3b8d --- /dev/null +++ b/node_modules/.bin/playwright.ps1 @@ -0,0 +1,28 @@ +#!/usr/bin/env pwsh +$basedir=Split-Path $MyInvocation.MyCommand.Definition -Parent + +$exe="" +if ($PSVersionTable.PSVersion -lt "6.0" -or $IsWindows) { + # Fix case when both the Windows and Linux builds of Node + # are installed in the same directory + $exe=".exe" +} +$ret=0 +if (Test-Path "$basedir/node$exe") { + # Support pipeline input + if ($MyInvocation.ExpectingInput) { + $input | & "$basedir/node$exe" "$basedir/../@playwright/test/cli.js" $args + } else { + & "$basedir/node$exe" "$basedir/../@playwright/test/cli.js" $args + } + $ret=$LASTEXITCODE +} else { + # Support pipeline input + if ($MyInvocation.ExpectingInput) { + $input | & "node$exe" "$basedir/../@playwright/test/cli.js" $args + } else { + & "node$exe" "$basedir/../@playwright/test/cli.js" $args + } + $ret=$LASTEXITCODE +} +exit $ret diff --git a/node_modules/.bin/semver b/node_modules/.bin/semver new file mode 120000 index 0000000..97c5327 --- /dev/null +++ b/node_modules/.bin/semver @@ -0,0 +1,16 @@ +#!/bin/sh +basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')") + +case `uname` in + *CYGWIN*|*MINGW*|*MSYS*) + if command -v cygpath > /dev/null 2>&1; then + basedir=`cygpath -w "$basedir"` + fi + ;; +esac + +if [ -x "$basedir/node" ]; then + exec "$basedir/node" "$basedir/../semver/bin/semver.js" "$@" +else + exec node "$basedir/../semver/bin/semver.js" "$@" +fi diff --git a/node_modules/.bin/semver.cmd b/node_modules/.bin/semver.cmd new file mode 100644 index 0000000..9913fa9 --- /dev/null +++ b/node_modules/.bin/semver.cmd @@ -0,0 +1,17 @@ +@ECHO off +GOTO start +:find_dp0 +SET dp0=%~dp0 +EXIT /b +:start +SETLOCAL +CALL :find_dp0 + +IF EXIST "%dp0%\node.exe" ( + SET "_prog=%dp0%\node.exe" +) ELSE ( + SET "_prog=node" + SET PATHEXT=%PATHEXT:;.JS;=;% +) + +endLocal & goto #_undefined_# 2>NUL || title %COMSPEC% & "%_prog%" "%dp0%\..\semver\bin\semver.js" %* diff --git a/node_modules/.bin/semver.ps1 b/node_modules/.bin/semver.ps1 new file mode 100644 index 0000000..314717a --- /dev/null +++ b/node_modules/.bin/semver.ps1 @@ -0,0 +1,28 @@ +#!/usr/bin/env pwsh +$basedir=Split-Path $MyInvocation.MyCommand.Definition -Parent + +$exe="" +if ($PSVersionTable.PSVersion -lt "6.0" -or $IsWindows) { + # Fix case when both the Windows and Linux builds of Node + # are installed in the same directory + $exe=".exe" +} +$ret=0 +if (Test-Path "$basedir/node$exe") { + # Support pipeline input + if ($MyInvocation.ExpectingInput) { + $input | & "$basedir/node$exe" "$basedir/../semver/bin/semver.js" $args + } else { + & "$basedir/node$exe" "$basedir/../semver/bin/semver.js" $args + } + $ret=$LASTEXITCODE +} else { + # Support pipeline input + if ($MyInvocation.ExpectingInput) { + $input | & "node$exe" "$basedir/../semver/bin/semver.js" $args + } else { + & "node$exe" "$basedir/../semver/bin/semver.js" $args + } + $ret=$LASTEXITCODE +} +exit $ret diff --git a/node_modules/.package-lock.json b/node_modules/.package-lock.json new file mode 100644 index 0000000..017628c --- /dev/null +++ b/node_modules/.package-lock.json @@ -0,0 +1,330 @@ +{ + "name": "playwright_python_framework", + "lockfileVersion": 3, + "requires": true, + "packages": { + "node_modules/@playwright/test": { + "version": "1.61.1", + "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.61.1.tgz", + "integrity": "sha512-8nKv6+0RJSL9FE4jYOEGXnPeM/Hg12qZpmqzZjRh3qM0Y7c3z1mrOTfFLids72RDQYVh9WpLEfR5WdpNX4fkig==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "playwright": "1.61.1" + }, + "bin": { + "playwright": "cli.js" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/acorn": { + "version": "8.16.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.16.0.tgz", + "integrity": "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==", + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-loose": { + "version": "8.5.2", + "resolved": "https://registry.npmjs.org/acorn-loose/-/acorn-loose-8.5.2.tgz", + "integrity": "sha512-PPvV6g8UGMGgjrMu+n/f9E/tCSkNQ2Y97eFvuVdJfG11+xdIeDcLyNdC8SHcrHbRqkfwLASdplyR6B6sKM1U4A==", + "license": "MIT", + "dependencies": { + "acorn": "^8.15.0" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-walk": { + "version": "8.3.5", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.5.tgz", + "integrity": "sha512-HEHNfbars9v4pgpW6SO1KSPkfoS0xVOM/9UzkJltjlsHZmJasxg8aXkuZa7SMf8vKGIBhpUsPluQSqhJFCqebw==", + "license": "MIT", + "dependencies": { + "acorn": "^8.11.0" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/commander": { + "version": "14.0.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-14.0.3.tgz", + "integrity": "sha512-H+y0Jo/T1RZ9qPP4Eh1pkcQcLRglraJaSLoyOtHxu6AapkjWVCy2Sit1QQ4x3Dng8qDlSsZEet7g5Pq06MvTgw==", + "license": "MIT", + "engines": { + "node": ">=20" + } + }, + "node_modules/console-grid": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/console-grid/-/console-grid-2.2.3.tgz", + "integrity": "sha512-+mecFacaFxGl+1G31IsCx41taUXuW2FxX+4xIE0TIPhgML+Jb9JFcBWGhhWerd1/vhScubdmHqTwOhB0KCUUAg==", + "license": "MIT" + }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/eight-colors": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/eight-colors/-/eight-colors-1.3.3.tgz", + "integrity": "sha512-4B54S2Qi4pJjeHmCbDIsveQZWQ/TSSQng4ixYJ9/SYHHpeS5nYK0pzcHvWzWUfRsvJQjwoIENhAwqg59thQceg==", + "license": "MIT" + }, + "node_modules/foreground-child": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz", + "integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==", + "license": "ISC", + "dependencies": { + "cross-spawn": "^7.0.6", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/html-escaper": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", + "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", + "license": "MIT" + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "license": "ISC" + }, + "node_modules/istanbul-lib-coverage": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz", + "integrity": "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-report": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz", + "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==", + "license": "BSD-3-Clause", + "dependencies": { + "istanbul-lib-coverage": "^3.0.0", + "make-dir": "^4.0.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-reports": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.2.0.tgz", + "integrity": "sha512-HGYWWS/ehqTV3xN10i23tkPkpH46MLCIMFNCaaKNavAXTF1RkqxawEPtnjnGZ6XKSInBKkiOA5BKS+aZiY3AvA==", + "license": "BSD-3-Clause", + "dependencies": { + "html-escaper": "^2.0.0", + "istanbul-lib-report": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/lz-utils": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/lz-utils/-/lz-utils-2.1.0.tgz", + "integrity": "sha512-CMkfimAypidTtWjNDxY8a1bc1mJdyEh04V2FfEQ5Zh8Nx4v7k850EYa+dOWGn9hKG5xOyHP5MkuduAZCTHRvJw==", + "license": "MIT" + }, + "node_modules/make-dir": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", + "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==", + "license": "MIT", + "dependencies": { + "semver": "^7.5.3" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/monocart-coverage-reports": { + "version": "2.12.9", + "resolved": "https://registry.npmjs.org/monocart-coverage-reports/-/monocart-coverage-reports-2.12.9.tgz", + "integrity": "sha512-vtFqbC3Egl4nVa1FSIrQvMPO6HZtb9lo+3IW7/crdvrLNW2IH8lUsxaK0TsKNmMO2mhFWwqQywLV2CZelqPgwA==", + "license": "MIT", + "dependencies": { + "acorn": "^8.15.0", + "acorn-loose": "^8.5.2", + "acorn-walk": "^8.3.4", + "commander": "^14.0.0", + "console-grid": "^2.2.3", + "eight-colors": "^1.3.1", + "foreground-child": "^3.3.1", + "istanbul-lib-coverage": "^3.2.2", + "istanbul-lib-report": "^3.0.1", + "istanbul-reports": "^3.2.0", + "lz-utils": "^2.1.0", + "monocart-locator": "^1.0.2" + }, + "bin": { + "mcr": "lib/cli.js" + } + }, + "node_modules/monocart-locator": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/monocart-locator/-/monocart-locator-1.0.2.tgz", + "integrity": "sha512-v8W5hJLcWMIxLCcSi/MHh+VeefI+ycFmGz23Froer9QzWjrbg4J3gFJBuI/T1VLNoYxF47bVPPxq8ZlNX4gVCw==", + "license": "MIT" + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/playwright": { + "version": "1.61.1", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.61.1.tgz", + "integrity": "sha512-DWnY5o3YbLWK4GovuAVwpqL+1VwGNdUGrRr++8j8PtQQzvAVZUIMjKQ90fY689sEJZJBbZVw1rXaOKSTitkzPQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "playwright-core": "1.61.1" + }, + "bin": { + "playwright": "cli.js" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "fsevents": "2.3.2" + } + }, + "node_modules/playwright-core": { + "version": "1.61.1", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.61.1.tgz", + "integrity": "sha512-h7Qlt6m4REp25qvIdvbDtVmD4LqVXfpRxhORv9L0jzETM05p4fuPJ3dKyuSXQxDSbXnmS79HAgi9589lGSpLkg==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "playwright-core": "cli.js" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/semver": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", + "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "license": "MIT", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "license": "ISC", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + } + } +} diff --git a/node_modules/@playwright/test/LICENSE b/node_modules/@playwright/test/LICENSE new file mode 100644 index 0000000..4ace03d --- /dev/null +++ b/node_modules/@playwright/test/LICENSE @@ -0,0 +1,202 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Portions Copyright (c) Microsoft Corporation. + Portions Copyright 2017 Google Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/node_modules/@playwright/test/NOTICE b/node_modules/@playwright/test/NOTICE new file mode 100644 index 0000000..814ec16 --- /dev/null +++ b/node_modules/@playwright/test/NOTICE @@ -0,0 +1,5 @@ +Playwright +Copyright (c) Microsoft Corporation + +This software contains code derived from the Puppeteer project (https://github.com/puppeteer/puppeteer), +available under the Apache 2.0 license (https://github.com/puppeteer/puppeteer/blob/master/LICENSE). diff --git a/node_modules/@playwright/test/README.md b/node_modules/@playwright/test/README.md new file mode 100644 index 0000000..d3abb8f --- /dev/null +++ b/node_modules/@playwright/test/README.md @@ -0,0 +1,318 @@ +# 🎭 Playwright + +[![npm version](https://img.shields.io/npm/v/playwright.svg)](https://www.npmjs.com/package/playwright) [![Chromium version](https://img.shields.io/badge/chromium-149.0.7827.55-blue.svg?logo=google-chrome)](https://www.chromium.org/Home) [![Firefox version](https://img.shields.io/badge/firefox-151.0-blue.svg?logo=firefoxbrowser)](https://www.mozilla.org/en-US/firefox/new/) [![WebKit version](https://img.shields.io/badge/webkit-26.5-blue.svg?logo=safari)](https://webkit.org/) [![Join Discord](https://img.shields.io/badge/join-discord-informational)](https://aka.ms/playwright/discord) + +## [Documentation](https://playwright.dev) | [API reference](https://playwright.dev/docs/api/class-playwright) + +Playwright is a framework for web automation and testing. It drives Chromium, Firefox, and WebKit with a single API — in your tests, in your scripts, and as a tool for AI agents. + +## Get Started + +Choose the path that fits your workflow: + +| | Best for | Install | +|---|---|---| +| **[Playwright Test](#playwright-test)** | End-to-end testing | `npm init playwright@latest` | +| **[Playwright CLI](#playwright-cli)** | Coding agents (Claude Code, Copilot) | `npm i -g @playwright/cli@latest` | +| **[Playwright MCP](#playwright-mcp)** | AI agents and LLM-driven automation | `npx @playwright/mcp@latest` | +| **[Playwright Library](#playwright-library)** | Browser automation scripts | `npm i playwright` | +| **[VS Code Extension](#vs-code-extension)** | Test authoring and debugging in VS Code | [Install from Marketplace](https://marketplace.visualstudio.com/items?itemName=ms-playwright.playwright) | + +--- + +## Playwright Test + +Playwright Test is a full-featured test runner built for end-to-end testing. It runs tests across Chromium, Firefox, and WebKit with full browser isolation, auto-waiting, and web-first assertions. + +### Install + +```bash +npm init playwright@latest +``` + +Or add manually: + +```bash +npm i -D @playwright/test +npx playwright install +``` + +### Write a test + +```TypeScript +import { test, expect } from '@playwright/test'; + +test('has title', async ({ page }) => { + await page.goto('https://playwright.dev/'); + await expect(page).toHaveTitle(/Playwright/); +}); + +test('get started link', async ({ page }) => { + await page.goto('https://playwright.dev/'); + await page.getByRole('link', { name: 'Get started' }).click(); + await expect(page.getByRole('heading', { name: 'Installation' })).toBeVisible(); +}); +``` + +### Run tests + +```bash +npx playwright test +``` + +Tests run in parallel across all configured browsers, in headless mode by default. Each test gets a fresh browser context — full isolation with near-zero overhead. + +### Key capabilities + +**Auto-wait and web-first assertions.** No artificial timeouts. Playwright waits for elements to be actionable, and assertions automatically retry until conditions are met. + +**Locators.** Find elements with resilient locators that mirror how users see the page: + +```TypeScript +page.getByRole('button', { name: 'Submit' }) +page.getByLabel('Email') +page.getByPlaceholder('Search...') +page.getByTestId('login-form') +``` + +**Test isolation.** Each test runs in its own browser context — equivalent to a fresh browser profile. Save authentication state once and reuse it across tests: + +```TypeScript +// Save state after login +await page.context().storageState({ path: 'auth.json' }); + +// Reuse in other tests +test.use({ storageState: 'auth.json' }); +``` + +**Tracing.** Capture execution traces, screenshots, and videos on failure. Inspect every action, DOM snapshot, network request, and console message in the [Trace Viewer](https://playwright.dev/docs/trace-viewer): + +```TypeScript +// playwright.config.ts +export default defineConfig({ + use: { + trace: 'on-first-retry', + }, +}); +``` + +```bash +npx playwright show-trace trace.zip +``` + + + +**Parallelism.** Tests run in parallel by default across all configured browsers. + +[Full testing documentation](https://playwright.dev/docs/intro) + +--- + +## Playwright CLI + +[Playwright CLI](https://github.com/microsoft/playwright-cli) is a command-line interface for browser automation designed for coding agents. It's more token-efficient than MCP — commands avoid loading large tool schemas and accessibility trees into the model context. + +### Install + +```bash +npm install -g @playwright/cli@latest +``` + +Optionally install skills for richer agent integration: + +```bash +playwright-cli install --skills +``` + +### Usage + +Point your coding agent at a task: + +``` +Test the "add todo" flow on https://demo.playwright.dev/todomvc using playwright-cli. +Take screenshots for all successful and failing scenarios. +``` + +Or run commands directly: + +```bash +playwright-cli open https://demo.playwright.dev/todomvc/ --headed +playwright-cli type "Buy groceries" +playwright-cli press Enter +playwright-cli screenshot +``` + +### Session monitoring + +Use `playwright-cli show` to open a visual dashboard with live screencast previews of all running browser sessions. Click any session to zoom in and take remote control. + +```bash +playwright-cli show +``` + + + +[Full CLI documentation](https://playwright.dev/agent-cli/introduction) | [GitHub](https://github.com/microsoft/playwright-cli) + +--- + +## Playwright MCP + +The [Playwright MCP server](https://github.com/microsoft/playwright-mcp) gives AI agents full browser control through the [Model Context Protocol](https://modelcontextprotocol.io). Agents interact with pages using structured accessibility snapshots — no vision models or screenshots required. + +### Setup + +Add to your MCP client (VS Code, Cursor, Claude Desktop, Windsurf, etc.): + +```json +{ + "mcpServers": { + "playwright": { + "command": "npx", + "args": ["@playwright/mcp@latest"] + } + } +} +``` + +**One-click install for VS Code:** + +[Install in VS Code](https://insiders.vscode.dev/redirect?url=vscode%3Amcp%2Finstall%3F%257B%2522name%2522%253A%2522playwright%2522%252C%2522command%2522%253A%2522npx%2522%252C%2522args%2522%253A%255B%2522%2540playwright%252Fmcp%2540latest%2522%255D%257D) + +**For Claude Code:** + +```bash +claude mcp add playwright npx @playwright/mcp@latest +``` + +### How it works + +Ask your AI assistant to interact with any web page: + +``` +Navigate to https://demo.playwright.dev/todomvc and add a few todo items. +``` + +The agent sees the page as a structured accessibility tree: + +``` +- heading "todos" [level=1] +- textbox "What needs to be done?" [ref=e5] +- listitem: + - checkbox "Toggle Todo" [ref=e10] + - text: "Buy groceries" +``` + +It uses element refs like `e5` and `e10` to click, type, and interact — deterministically and without visual ambiguity. Tools cover navigation, form filling, screenshots, network mocking, storage management, and more. + +[Full MCP documentation](https://playwright.dev/mcp/introduction) | [GitHub](https://github.com/microsoft/playwright-mcp) + +--- + +## Playwright Library + +Use `playwright` as a library for browser automation scripts — web scraping, PDF generation, screenshot capture, and any workflow that needs programmatic browser control without a test runner. + +### Install + +```bash +npm i playwright +``` + +### Examples + +**Take a screenshot:** + +```TypeScript +import { chromium } from 'playwright'; + +const browser = await chromium.launch(); +const page = await browser.newPage(); +await page.goto('https://playwright.dev/'); +await page.screenshot({ path: 'screenshot.png' }); +await browser.close(); +``` + +**Generate a PDF:** + +```TypeScript +import { chromium } from 'playwright'; + +const browser = await chromium.launch(); +const page = await browser.newPage(); +await page.goto('https://playwright.dev/'); +await page.pdf({ path: 'page.pdf', format: 'A4' }); +await browser.close(); +``` + +**Emulate a mobile device:** + +```TypeScript +import { chromium, devices } from 'playwright'; + +const browser = await chromium.launch(); +const context = await browser.newContext(devices['iPhone 15']); +const page = await context.newPage(); +await page.goto('https://playwright.dev/'); +await page.screenshot({ path: 'mobile.png' }); +await browser.close(); +``` + +**Intercept network requests:** + +```TypeScript +import { chromium } from 'playwright'; + +const browser = await chromium.launch(); +const page = await browser.newPage(); +await page.route('**/*.{png,jpg,jpeg}', route => route.abort()); +await page.goto('https://playwright.dev/'); +await browser.close(); +``` + +[Library documentation](https://playwright.dev/docs/library) | [API reference](https://playwright.dev/docs/api/class-playwright) + +--- + +## VS Code Extension + +The [Playwright VS Code extension](https://marketplace.visualstudio.com/items?itemName=ms-playwright.playwright) brings test running, debugging, and code generation directly into your editor. + + + +**Run and debug tests** from the editor with a single click. Set breakpoints, inspect variables, and step through test execution with a live browser view. + +**Generate tests with CodeGen.** Click "Record new" to open a browser — navigate and interact with your app while Playwright writes the test code for you. + +**Pick locators.** Hover over any element in the browser to see the best available locator, then click to copy it to your clipboard. + +**Trace Viewer integration.** Enable "Show Trace Viewer" in the sidebar to get a full execution trace after each test run — DOM snapshots, network requests, console logs, and screenshots at every step. + +[Install the extension](https://marketplace.visualstudio.com/items?itemName=ms-playwright.playwright) | [VS Code guide](https://playwright.dev/docs/getting-started-vscode) + +--- + +## Cross-Browser Support + +| | Linux | macOS | Windows | +| :--- | :---: | :---: | :---: | +| Chromium1 149.0.7827.55 | :white_check_mark: | :white_check_mark: | :white_check_mark: | +| WebKit 26.5 | :white_check_mark: | :white_check_mark: | :white_check_mark: | +| Firefox 151.0 | :white_check_mark: | :white_check_mark: | :white_check_mark: | + +Headless and headed execution on all platforms. 1 Uses [Chrome for Testing](https://developer.chrome.com/blog/chrome-for-testing) by default. + +## Other Languages + +Playwright is also available for [Python](https://playwright.dev/python/docs/intro), [.NET](https://playwright.dev/dotnet/docs/intro), and [Java](https://playwright.dev/java/docs/intro). + +## Resources + +* [Documentation](https://playwright.dev) +* [API reference](https://playwright.dev/docs/api/class-playwright) +* [MCP server](https://github.com/microsoft/playwright-mcp) +* [CLI for coding agents](https://github.com/microsoft/playwright-cli) +* [VS Code extension](https://github.com/microsoft/playwright-vscode) +* [Contribution guide](CONTRIBUTING.md) +* [Changelog](https://github.com/microsoft/playwright/releases) +* [Discord](https://aka.ms/playwright/discord) diff --git a/node_modules/@playwright/test/cli.js b/node_modules/@playwright/test/cli.js new file mode 100644 index 0000000..e42facb --- /dev/null +++ b/node_modules/@playwright/test/cli.js @@ -0,0 +1,19 @@ +#!/usr/bin/env node +/** + * Copyright (c) Microsoft Corporation. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +const { program } = require('playwright/lib/program'); +program.parse(process.argv); diff --git a/node_modules/@playwright/test/index.d.ts b/node_modules/@playwright/test/index.d.ts new file mode 100644 index 0000000..8d99c91 --- /dev/null +++ b/node_modules/@playwright/test/index.d.ts @@ -0,0 +1,18 @@ +/** + * Copyright (c) Microsoft Corporation. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export * from 'playwright/test'; +export { default } from 'playwright/test'; diff --git a/node_modules/@playwright/test/index.js b/node_modules/@playwright/test/index.js new file mode 100644 index 0000000..8536f06 --- /dev/null +++ b/node_modules/@playwright/test/index.js @@ -0,0 +1,17 @@ +/** + * Copyright (c) Microsoft Corporation. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +module.exports = require('playwright/test'); diff --git a/node_modules/@playwright/test/index.mjs b/node_modules/@playwright/test/index.mjs new file mode 100644 index 0000000..8d99c91 --- /dev/null +++ b/node_modules/@playwright/test/index.mjs @@ -0,0 +1,18 @@ +/** + * Copyright (c) Microsoft Corporation. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export * from 'playwright/test'; +export { default } from 'playwright/test'; diff --git a/node_modules/@playwright/test/package.json b/node_modules/@playwright/test/package.json new file mode 100644 index 0000000..385f2ef --- /dev/null +++ b/node_modules/@playwright/test/package.json @@ -0,0 +1,35 @@ +{ + "name": "@playwright/test", + "version": "1.61.1", + "description": "A high-level API to automate web browsers", + "repository": { + "type": "git", + "url": "git+https://github.com/microsoft/playwright.git" + }, + "homepage": "https://playwright.dev", + "engines": { + "node": ">=18" + }, + "author": { + "name": "Microsoft Corporation" + }, + "license": "Apache-2.0", + "exports": { + ".": { + "types": "./index.d.ts", + "import": "./index.mjs", + "require": "./index.js", + "default": "./index.js" + }, + "./cli": "./cli.js", + "./package.json": "./package.json", + "./reporter": "./reporter.js" + }, + "bin": { + "playwright": "cli.js" + }, + "scripts": {}, + "dependencies": { + "playwright": "1.61.1" + } +} diff --git a/node_modules/@playwright/test/reporter.d.ts b/node_modules/@playwright/test/reporter.d.ts new file mode 100644 index 0000000..806d13f --- /dev/null +++ b/node_modules/@playwright/test/reporter.d.ts @@ -0,0 +1,17 @@ +/** + * Copyright (c) Microsoft Corporation. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export * from 'playwright/types/testReporter'; diff --git a/node_modules/@playwright/test/reporter.js b/node_modules/@playwright/test/reporter.js new file mode 100644 index 0000000..485e880 --- /dev/null +++ b/node_modules/@playwright/test/reporter.js @@ -0,0 +1,17 @@ +/** + * Copyright (c) Microsoft Corporation. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// We only export types in reporter.d.ts. diff --git a/node_modules/@playwright/test/reporter.mjs b/node_modules/@playwright/test/reporter.mjs new file mode 100644 index 0000000..485e880 --- /dev/null +++ b/node_modules/@playwright/test/reporter.mjs @@ -0,0 +1,17 @@ +/** + * Copyright (c) Microsoft Corporation. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// We only export types in reporter.d.ts. diff --git a/node_modules/acorn-loose/CHANGELOG.md b/node_modules/acorn-loose/CHANGELOG.md new file mode 100644 index 0000000..c0b9098 --- /dev/null +++ b/node_modules/acorn-loose/CHANGELOG.md @@ -0,0 +1,165 @@ +## 8.5.2 (2025-07-01) + +### Bug fixes + +Use the proper version of `acorn` as a dependency. + +## 8.5.1 (2025-06-08) + +### Bug fixes + +Handle tokenizer exceptions raised by invalid numeric separators. + +## 8.5.0 (2025-04-17) + +### New features + +Support ES2025 import attributes. + +## 8.4.0 (2023-10-26) + +### Bug fixes + +Fix an issue where a slash after a call to a propery named the same as some keywords would be tokenized as a regular expression. + +Fix a bug where the parser would raise an error when an invalid escape was included in an identifier after a keyword. + +### New features + +Use a set of new, much more precise, TypeScript types. + +## 8.3.0 (2021-12-27) + +### New features + +Support quoted export names. + +Support class private fields with the `in` operator. + +### Bug fixes + +Fix a bug that caused semicolons after `export *` statements to be parsed as empty statements. + +## 8.2.1 (2021-09-06) + +### Bug fixes + +Depend on the proper version of acorn. + +## 8.2.0 (2021-09-06) + +### New features + +Add support for ES2022 class static blocks. + +## 8.1.0 (2021-04-24) + +### New features + +Add support for ES2022 class fields and private methods. + +## 8.0.2 (2021-01-25) + +### Bug fixes + +Adjust package.json to work with Node 12.16.0 and 13.0-13.6. + +## 8.0.1 (2020-10-11) + +### Bug fixes + +Allow `for await` at the top level. + +## 8.0.0 (2020-08-12) + +### New features + +The package can now be loaded directly as an ECMAScript module in node 13+. + +### Breaking changes + +The `ecmaVersion` option is now required. For the moment, omitting it will still work with a warning, but that will change in a future release. + +## 7.1.0 (2020-06-11) + +### Bug fixes + +Fix various issues in regexp validation. + +### New features + +Add support for `import.meta`. + +Add support for optional chaining (`?.`) and nullish coalescing (`??`). + +Support `export * as ns from "source"`. + +## 7.0.0 (2019-08-12) + +### Breaking changes + +Changes the node format for dynamic imports to use the `ImportExpression` node type, as defined in [ESTree](https://github.com/estree/estree/blob/master/es2020.md#importexpression). + +## 6.1.0 (2019-07-04) + +### New features + +Support bigint syntax. + +Support dynamic import. + +## 6.0.0 (2018-09-14) + +### Breaking changes + +This module has been moved into its own package, `acorn-loose`. + +Plugins work differently, and will have to be rewritten to work with this version. + +The `parse_dammit` function is now simply called `parse`. + +## 5.1.0 (2017-07-05) + +### Bug fixes + +Make the ES module version of the loose parser actually work. + +## 4.0.4 (2016-12-19) + +### Bug fixes + +Fix issue with loading acorn_loose.js with an AMD loader. + +## 3.2.0 (2016-06-07) + +### Bug fixes + +Don't crash when the loose parser is called without options object. + +## 3.1.0 (2016-04-18) + +### Bug fixes + +Fix issue where the loose parser created invalid TemplateElement nodes for unclosed template literals. + +## 2.7.0 (2016-01-04) + +### Fixes + +Make sure the loose parser always attaches a `local` property to `ImportNamespaceSpecifier` nodes. + +## 2.6.4 (2015-11-12) + +### Fixes + +Fix crash in loose parser when parsing invalid object pattern. + +### New features + +Support plugins in the loose parser. + +## 2.5.0 (2015-10-27) + +### Fixes + +In the loose parser, don't allow non-string-literals as import sources. diff --git a/node_modules/acorn-loose/LICENSE b/node_modules/acorn-loose/LICENSE new file mode 100644 index 0000000..d6be6db --- /dev/null +++ b/node_modules/acorn-loose/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (C) 2012-2020 by various contributors (see AUTHORS) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/node_modules/acorn-loose/README.md b/node_modules/acorn-loose/README.md new file mode 100644 index 0000000..ac1d2d3 --- /dev/null +++ b/node_modules/acorn-loose/README.md @@ -0,0 +1,64 @@ +# Acorn loose parser + +An error-tolerant JavaScript parser written in JavaScript. + +This parser will parse _any_ text into an +[ESTree](https://github.com/estree/estree) syntax tree that is a +reasonable approximation of what it might mean as a JavaScript +program. + +It will, to recover from missing brackets, treat whitespace as +significant, which has the downside that it might mis-parse a valid +but weirdly indented file. It is recommended to always try a parse +with the regular `acorn` parser first, and only fall back to this +parser when that one finds syntax errors. + +## Community + +Acorn is open source software released under an +[MIT license](https://github.com/acornjs/acorn/blob/master/acorn-loose/LICENSE). + +You are welcome to [report +bugs](https://github.com/acornjs/acorn/issues) or create pull requests +on [github](https://github.com/acornjs/acorn). + +## Installation + +The easiest way to install acorn-loose is from [`npm`](https://www.npmjs.com/): + +```sh +npm install acorn-loose +``` + +Alternately, you can download the source and build acorn yourself: + +```sh +git clone https://github.com/acornjs/acorn.git +cd acorn +npm install +``` + +## Interface + +**parse**`(input, options)` takes an input string and a set of options +(the same options as +[acorn](https://github.com/acornjs/acorn/blob/master/acorn/README.md) +takes), and returns a syntax tree, even if the code isn't +syntactically valid. It'll insert identifier nodes with name `"✖"` as +placeholders in places where it can't make sense of the input. Depends +on the `acorn` package, because it uses the same tokenizer. + +```javascript +var acornLoose = require("acorn-loose"); +console.log(acornLoose.parse("1 / * 4 )[2]", {ecmaVersion: 2020})); +``` + +Like the regular parser, the loose parser supports plugins. You can +take the **`LooseParser`** class exported by the module, and call its +static `extend` method with one or more plugins to get a customized +parser class. The class has a static `parse` method that acts like the +top-level `parse` method. + +**isDummy**`(node)` takes a `Node` and returns `true` if it is a dummy node +inserted by the parser. The function performs a simple equality check on the +node's name. diff --git a/node_modules/acorn-loose/dist/acorn-loose.d.mts b/node_modules/acorn-loose/dist/acorn-loose.d.mts new file mode 100644 index 0000000..b8f07d3 --- /dev/null +++ b/node_modules/acorn-loose/dist/acorn-loose.d.mts @@ -0,0 +1,10 @@ +import * as acorn from "acorn" + +export const LooseParser: typeof acorn.Parser + +export function parse (input: string, options: acorn.Options): acorn.Program + +/** + * returns `true` if it is a dummy node inserted by the parser. The function performs a simple equality check on the node's name. + */ +export function isDummy(node: acorn.Node): boolean diff --git a/node_modules/acorn-loose/dist/acorn-loose.d.ts b/node_modules/acorn-loose/dist/acorn-loose.d.ts new file mode 100644 index 0000000..b8f07d3 --- /dev/null +++ b/node_modules/acorn-loose/dist/acorn-loose.d.ts @@ -0,0 +1,10 @@ +import * as acorn from "acorn" + +export const LooseParser: typeof acorn.Parser + +export function parse (input: string, options: acorn.Options): acorn.Program + +/** + * returns `true` if it is a dummy node inserted by the parser. The function performs a simple equality check on the node's name. + */ +export function isDummy(node: acorn.Node): boolean diff --git a/node_modules/acorn-loose/dist/acorn-loose.js b/node_modules/acorn-loose/dist/acorn-loose.js new file mode 100644 index 0000000..57391f0 --- /dev/null +++ b/node_modules/acorn-loose/dist/acorn-loose.js @@ -0,0 +1,1638 @@ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('acorn')) : + typeof define === 'function' && define.amd ? define(['exports', 'acorn'], factory) : + (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory((global.acorn = global.acorn || {}, global.acorn.loose = {}), global.acorn)); +})(this, (function (exports, acorn) { 'use strict'; + + var dummyValue = "✖"; + + function isDummy(node) { return node.name === dummyValue } + + function noop() {} + + var LooseParser = function LooseParser(input, options) { + if ( options === void 0 ) options = {}; + + this.toks = this.constructor.BaseParser.tokenizer(input, options); + this.options = this.toks.options; + this.input = this.toks.input; + this.tok = this.last = {type: acorn.tokTypes.eof, start: 0, end: 0}; + this.tok.validateRegExpFlags = noop; + this.tok.validateRegExpPattern = noop; + if (this.options.locations) { + var here = this.toks.curPosition(); + this.tok.loc = new acorn.SourceLocation(this.toks, here, here); + } + this.ahead = []; // Tokens ahead + this.context = []; // Indentation contexted + this.curIndent = 0; + this.curLineStart = 0; + this.nextLineStart = this.lineEnd(this.curLineStart) + 1; + this.inAsync = false; + this.inGenerator = false; + this.inFunction = false; + }; + + LooseParser.prototype.startNode = function startNode () { + return new acorn.Node(this.toks, this.tok.start, this.options.locations ? this.tok.loc.start : null) + }; + + LooseParser.prototype.storeCurrentPos = function storeCurrentPos () { + return this.options.locations ? [this.tok.start, this.tok.loc.start] : this.tok.start + }; + + LooseParser.prototype.startNodeAt = function startNodeAt (pos) { + if (this.options.locations) { + return new acorn.Node(this.toks, pos[0], pos[1]) + } else { + return new acorn.Node(this.toks, pos) + } + }; + + LooseParser.prototype.finishNode = function finishNode (node, type) { + node.type = type; + node.end = this.last.end; + if (this.options.locations) + { node.loc.end = this.last.loc.end; } + if (this.options.ranges) + { node.range[1] = this.last.end; } + return node + }; + + LooseParser.prototype.dummyNode = function dummyNode (type) { + var dummy = this.startNode(); + dummy.type = type; + dummy.end = dummy.start; + if (this.options.locations) + { dummy.loc.end = dummy.loc.start; } + if (this.options.ranges) + { dummy.range[1] = dummy.start; } + this.last = {type: acorn.tokTypes.name, start: dummy.start, end: dummy.start, loc: dummy.loc}; + return dummy + }; + + LooseParser.prototype.dummyIdent = function dummyIdent () { + var dummy = this.dummyNode("Identifier"); + dummy.name = dummyValue; + return dummy + }; + + LooseParser.prototype.dummyString = function dummyString () { + var dummy = this.dummyNode("Literal"); + dummy.value = dummy.raw = dummyValue; + return dummy + }; + + LooseParser.prototype.eat = function eat (type) { + if (this.tok.type === type) { + this.next(); + return true + } else { + return false + } + }; + + LooseParser.prototype.isContextual = function isContextual (name) { + return this.tok.type === acorn.tokTypes.name && this.tok.value === name + }; + + LooseParser.prototype.eatContextual = function eatContextual (name) { + return this.tok.value === name && this.eat(acorn.tokTypes.name) + }; + + LooseParser.prototype.canInsertSemicolon = function canInsertSemicolon () { + return this.tok.type === acorn.tokTypes.eof || this.tok.type === acorn.tokTypes.braceR || + acorn.lineBreak.test(this.input.slice(this.last.end, this.tok.start)) + }; + + LooseParser.prototype.semicolon = function semicolon () { + return this.eat(acorn.tokTypes.semi) + }; + + LooseParser.prototype.expect = function expect (type) { + if (this.eat(type)) { return true } + for (var i = 1; i <= 2; i++) { + if (this.lookAhead(i).type === type) { + for (var j = 0; j < i; j++) { this.next(); } + return true + } + } + }; + + LooseParser.prototype.pushCx = function pushCx () { + this.context.push(this.curIndent); + }; + + LooseParser.prototype.popCx = function popCx () { + this.curIndent = this.context.pop(); + }; + + LooseParser.prototype.lineEnd = function lineEnd (pos) { + while (pos < this.input.length && !acorn.isNewLine(this.input.charCodeAt(pos))) { ++pos; } + return pos + }; + + LooseParser.prototype.indentationAfter = function indentationAfter (pos) { + for (var count = 0;; ++pos) { + var ch = this.input.charCodeAt(pos); + if (ch === 32) { ++count; } + else if (ch === 9) { count += this.options.tabSize; } + else { return count } + } + }; + + LooseParser.prototype.closes = function closes (closeTok, indent, line, blockHeuristic) { + if (this.tok.type === closeTok || this.tok.type === acorn.tokTypes.eof) { return true } + return line !== this.curLineStart && this.curIndent < indent && this.tokenStartsLine() && + (!blockHeuristic || this.nextLineStart >= this.input.length || + this.indentationAfter(this.nextLineStart) < indent) + }; + + LooseParser.prototype.tokenStartsLine = function tokenStartsLine () { + for (var p = this.tok.start - 1; p >= this.curLineStart; --p) { + var ch = this.input.charCodeAt(p); + if (ch !== 9 && ch !== 32) { return false } + } + return true + }; + + LooseParser.prototype.extend = function extend (name, f) { + this[name] = f(this[name]); + }; + + LooseParser.prototype.parse = function parse () { + this.next(); + return this.parseTopLevel() + }; + + LooseParser.extend = function extend () { + var plugins = [], len = arguments.length; + while ( len-- ) plugins[ len ] = arguments[ len ]; + + var cls = this; + for (var i = 0; i < plugins.length; i++) { cls = plugins[i](cls); } + return cls + }; + + LooseParser.parse = function parse (input, options) { + return new this(input, options).parse() + }; + + // Allows plugins to extend the base parser / tokenizer used + LooseParser.BaseParser = acorn.Parser; + + var lp$2 = LooseParser.prototype; + + function isSpace(ch) { + return (ch < 14 && ch > 8) || ch === 32 || ch === 160 || acorn.isNewLine(ch) + } + + lp$2.next = function() { + this.last = this.tok; + if (this.ahead.length) + { this.tok = this.ahead.shift(); } + else + { this.tok = this.readToken(); } + + if (this.tok.start >= this.nextLineStart) { + while (this.tok.start >= this.nextLineStart) { + this.curLineStart = this.nextLineStart; + this.nextLineStart = this.lineEnd(this.curLineStart) + 1; + } + this.curIndent = this.indentationAfter(this.curLineStart); + } + }; + + lp$2.readToken = function() { + for (;;) { + try { + this.toks.next(); + if (this.toks.type === acorn.tokTypes.dot && + this.input.substr(this.toks.end, 1) === "." && + this.options.ecmaVersion >= 6) { + this.toks.end++; + this.toks.type = acorn.tokTypes.ellipsis; + } + return new acorn.Token(this.toks) + } catch (e) { + if (!(e instanceof SyntaxError)) { throw e } + + // Try to skip some text, based on the error message, and then continue + var msg = e.message, pos = e.raisedAt, replace = true; + if (/unterminated/i.test(msg)) { + pos = this.lineEnd(e.pos + 1); + if (/string/.test(msg)) { + replace = {start: e.pos, end: pos, type: acorn.tokTypes.string, value: this.input.slice(e.pos + 1, pos)}; + } else if (/regular expr/i.test(msg)) { + var re = this.input.slice(e.pos, pos); + try { re = new RegExp(re); } catch (e$1) { /* ignore compilation error due to new syntax */ } + replace = {start: e.pos, end: pos, type: acorn.tokTypes.regexp, value: re}; + } else if (/template/.test(msg)) { + replace = { + start: e.pos, + end: pos, + type: acorn.tokTypes.template, + value: this.input.slice(e.pos, pos) + }; + } else { + replace = false; + } + } else if (/invalid (unicode|regexp|number)|expecting unicode|octal literal|is reserved|directly after number|expected number in radix|numeric separator/i.test(msg)) { + while (pos < this.input.length && !isSpace(this.input.charCodeAt(pos))) { ++pos; } + } else if (/character escape|expected hexadecimal/i.test(msg)) { + while (pos < this.input.length) { + var ch = this.input.charCodeAt(pos++); + if (ch === 34 || ch === 39 || acorn.isNewLine(ch)) { break } + } + } else if (/unexpected character/i.test(msg)) { + pos++; + replace = false; + } else if (/regular expression/i.test(msg)) { + replace = true; + } else { + throw e + } + this.resetTo(pos); + if (replace === true) { replace = {start: pos, end: pos, type: acorn.tokTypes.name, value: dummyValue}; } + if (replace) { + if (this.options.locations) + { replace.loc = new acorn.SourceLocation( + this.toks, + acorn.getLineInfo(this.input, replace.start), + acorn.getLineInfo(this.input, replace.end)); } + return replace + } + } + } + }; + + lp$2.resetTo = function(pos) { + this.toks.pos = pos; + this.toks.containsEsc = false; + var ch = this.input.charAt(pos - 1); + this.toks.exprAllowed = !ch || /[[{(,;:?/*=+\-~!|&%^<>]/.test(ch) || + /[enwfd]/.test(ch) && + /\b(case|else|return|throw|new|in|(instance|type)?of|delete|void)$/.test(this.input.slice(pos - 10, pos)); + + if (this.options.locations) { + this.toks.curLine = 1; + this.toks.lineStart = acorn.lineBreakG.lastIndex = 0; + var match; + while ((match = acorn.lineBreakG.exec(this.input)) && match.index < pos) { + ++this.toks.curLine; + this.toks.lineStart = match.index + match[0].length; + } + } + }; + + lp$2.lookAhead = function(n) { + while (n > this.ahead.length) + { this.ahead.push(this.readToken()); } + return this.ahead[n - 1] + }; + + var lp$1 = LooseParser.prototype; + + lp$1.parseTopLevel = function() { + var node = this.startNodeAt(this.options.locations ? [0, acorn.getLineInfo(this.input, 0)] : 0); + node.body = []; + while (this.tok.type !== acorn.tokTypes.eof) { node.body.push(this.parseStatement()); } + this.toks.adaptDirectivePrologue(node.body); + this.last = this.tok; + node.sourceType = this.options.sourceType === "commonjs" ? "script" : this.options.sourceType; + return this.finishNode(node, "Program") + }; + + lp$1.parseStatement = function() { + var starttype = this.tok.type, node = this.startNode(), kind; + + if (this.toks.isLet()) { + starttype = acorn.tokTypes._var; + kind = "let"; + } + + switch (starttype) { + case acorn.tokTypes._break: case acorn.tokTypes._continue: + this.next(); + var isBreak = starttype === acorn.tokTypes._break; + if (this.semicolon() || this.canInsertSemicolon()) { + node.label = null; + } else { + node.label = this.tok.type === acorn.tokTypes.name ? this.parseIdent() : null; + this.semicolon(); + } + return this.finishNode(node, isBreak ? "BreakStatement" : "ContinueStatement") + + case acorn.tokTypes._debugger: + this.next(); + this.semicolon(); + return this.finishNode(node, "DebuggerStatement") + + case acorn.tokTypes._do: + this.next(); + node.body = this.parseStatement(); + node.test = this.eat(acorn.tokTypes._while) ? this.parseParenExpression() : this.dummyIdent(); + this.semicolon(); + return this.finishNode(node, "DoWhileStatement") + + case acorn.tokTypes._for: + this.next(); // `for` keyword + var isAwait = this.options.ecmaVersion >= 9 && this.eatContextual("await"); + + this.pushCx(); + this.expect(acorn.tokTypes.parenL); + if (this.tok.type === acorn.tokTypes.semi) { return this.parseFor(node, null) } + var isLet = this.toks.isLet(); + var isAwaitUsing = this.toks.isAwaitUsing(true); + var isUsing = !isAwaitUsing && this.toks.isUsing(true); + + if (isLet || this.tok.type === acorn.tokTypes._var || this.tok.type === acorn.tokTypes._const || isUsing || isAwaitUsing) { + var kind$1 = isLet ? "let" : isUsing ? "using" : isAwaitUsing ? "await using" : this.tok.value; + var init$1 = this.startNode(); + if (isUsing || isAwaitUsing) { + if (isAwaitUsing) { this.next(); } + this.parseVar(init$1, true, kind$1); + } else { + init$1 = this.parseVar(init$1, true, kind$1); + } + + if (init$1.declarations.length === 1 && (this.tok.type === acorn.tokTypes._in || this.isContextual("of"))) { + if (this.options.ecmaVersion >= 9 && this.tok.type !== acorn.tokTypes._in) { + node.await = isAwait; + } + return this.parseForIn(node, init$1) + } + return this.parseFor(node, init$1) + } + var init = this.parseExpression(true); + if (this.tok.type === acorn.tokTypes._in || this.isContextual("of")) { + if (this.options.ecmaVersion >= 9 && this.tok.type !== acorn.tokTypes._in) { + node.await = isAwait; + } + return this.parseForIn(node, this.toAssignable(init)) + } + return this.parseFor(node, init) + + case acorn.tokTypes._function: + this.next(); + return this.parseFunction(node, true) + + case acorn.tokTypes._if: + this.next(); + node.test = this.parseParenExpression(); + node.consequent = this.parseStatement(); + node.alternate = this.eat(acorn.tokTypes._else) ? this.parseStatement() : null; + return this.finishNode(node, "IfStatement") + + case acorn.tokTypes._return: + this.next(); + if (this.eat(acorn.tokTypes.semi) || this.canInsertSemicolon()) { node.argument = null; } + else { node.argument = this.parseExpression(); this.semicolon(); } + return this.finishNode(node, "ReturnStatement") + + case acorn.tokTypes._switch: + var blockIndent = this.curIndent, line = this.curLineStart; + this.next(); + node.discriminant = this.parseParenExpression(); + node.cases = []; + this.pushCx(); + this.expect(acorn.tokTypes.braceL); + + var cur; + while (!this.closes(acorn.tokTypes.braceR, blockIndent, line, true)) { + if (this.tok.type === acorn.tokTypes._case || this.tok.type === acorn.tokTypes._default) { + var isCase = this.tok.type === acorn.tokTypes._case; + if (cur) { this.finishNode(cur, "SwitchCase"); } + node.cases.push(cur = this.startNode()); + cur.consequent = []; + this.next(); + if (isCase) { cur.test = this.parseExpression(); } + else { cur.test = null; } + this.expect(acorn.tokTypes.colon); + } else { + if (!cur) { + node.cases.push(cur = this.startNode()); + cur.consequent = []; + cur.test = null; + } + cur.consequent.push(this.parseStatement()); + } + } + if (cur) { this.finishNode(cur, "SwitchCase"); } + this.popCx(); + this.eat(acorn.tokTypes.braceR); + return this.finishNode(node, "SwitchStatement") + + case acorn.tokTypes._throw: + this.next(); + node.argument = this.parseExpression(); + this.semicolon(); + return this.finishNode(node, "ThrowStatement") + + case acorn.tokTypes._try: + this.next(); + node.block = this.parseBlock(); + node.handler = null; + if (this.tok.type === acorn.tokTypes._catch) { + var clause = this.startNode(); + this.next(); + if (this.eat(acorn.tokTypes.parenL)) { + clause.param = this.toAssignable(this.parseExprAtom(), true); + this.expect(acorn.tokTypes.parenR); + } else { + clause.param = null; + } + clause.body = this.parseBlock(); + node.handler = this.finishNode(clause, "CatchClause"); + } + node.finalizer = this.eat(acorn.tokTypes._finally) ? this.parseBlock() : null; + if (!node.handler && !node.finalizer) { return node.block } + return this.finishNode(node, "TryStatement") + + case acorn.tokTypes._var: + case acorn.tokTypes._const: + return this.parseVar(node, false, kind || this.tok.value) + + case acorn.tokTypes._while: + this.next(); + node.test = this.parseParenExpression(); + node.body = this.parseStatement(); + return this.finishNode(node, "WhileStatement") + + case acorn.tokTypes._with: + this.next(); + node.object = this.parseParenExpression(); + node.body = this.parseStatement(); + return this.finishNode(node, "WithStatement") + + case acorn.tokTypes.braceL: + return this.parseBlock() + + case acorn.tokTypes.semi: + this.next(); + return this.finishNode(node, "EmptyStatement") + + case acorn.tokTypes._class: + return this.parseClass(true) + + case acorn.tokTypes._import: + if (this.options.ecmaVersion > 10) { + var nextType = this.lookAhead(1).type; + if (nextType === acorn.tokTypes.parenL || nextType === acorn.tokTypes.dot) { + node.expression = this.parseExpression(); + this.semicolon(); + return this.finishNode(node, "ExpressionStatement") + } + } + + return this.parseImport() + + case acorn.tokTypes._export: + return this.parseExport() + + default: + if (this.toks.isAsyncFunction()) { + this.next(); + this.next(); + return this.parseFunction(node, true, true) + } + + if (this.toks.isUsing(false)) { + return this.parseVar(node, false, "using") + } + + if (this.toks.isAwaitUsing(false)) { + this.next(); + return this.parseVar(node, false, "await using") + } + + var expr = this.parseExpression(); + if (isDummy(expr)) { + this.next(); + if (this.tok.type === acorn.tokTypes.eof) { return this.finishNode(node, "EmptyStatement") } + return this.parseStatement() + } else if (starttype === acorn.tokTypes.name && expr.type === "Identifier" && this.eat(acorn.tokTypes.colon)) { + node.body = this.parseStatement(); + node.label = expr; + return this.finishNode(node, "LabeledStatement") + } else { + node.expression = expr; + this.semicolon(); + return this.finishNode(node, "ExpressionStatement") + } + } + }; + + lp$1.parseBlock = function() { + var node = this.startNode(); + this.pushCx(); + this.expect(acorn.tokTypes.braceL); + var blockIndent = this.curIndent, line = this.curLineStart; + node.body = []; + while (!this.closes(acorn.tokTypes.braceR, blockIndent, line, true)) + { node.body.push(this.parseStatement()); } + this.popCx(); + this.eat(acorn.tokTypes.braceR); + return this.finishNode(node, "BlockStatement") + }; + + lp$1.parseFor = function(node, init) { + node.init = init; + node.test = node.update = null; + if (this.eat(acorn.tokTypes.semi) && this.tok.type !== acorn.tokTypes.semi) { node.test = this.parseExpression(); } + if (this.eat(acorn.tokTypes.semi) && this.tok.type !== acorn.tokTypes.parenR) { node.update = this.parseExpression(); } + this.popCx(); + this.expect(acorn.tokTypes.parenR); + node.body = this.parseStatement(); + return this.finishNode(node, "ForStatement") + }; + + lp$1.parseForIn = function(node, init) { + var type = this.tok.type === acorn.tokTypes._in ? "ForInStatement" : "ForOfStatement"; + this.next(); + node.left = init; + node.right = this.parseExpression(); + this.popCx(); + this.expect(acorn.tokTypes.parenR); + node.body = this.parseStatement(); + return this.finishNode(node, type) + }; + + lp$1.parseVar = function(node, noIn, kind) { + node.kind = kind; + this.next(); + node.declarations = []; + do { + var decl = this.startNode(); + decl.id = this.options.ecmaVersion >= 6 ? this.toAssignable(this.parseExprAtom(), true) : this.parseIdent(); + decl.init = this.eat(acorn.tokTypes.eq) ? this.parseMaybeAssign(noIn) : null; + node.declarations.push(this.finishNode(decl, "VariableDeclarator")); + } while (this.eat(acorn.tokTypes.comma)) + if (!node.declarations.length) { + var decl$1 = this.startNode(); + decl$1.id = this.dummyIdent(); + node.declarations.push(this.finishNode(decl$1, "VariableDeclarator")); + } + if (!noIn) { this.semicolon(); } + return this.finishNode(node, "VariableDeclaration") + }; + + lp$1.parseClass = function(isStatement) { + var node = this.startNode(); + this.next(); + if (this.tok.type === acorn.tokTypes.name) { node.id = this.parseIdent(); } + else if (isStatement === true) { node.id = this.dummyIdent(); } + else { node.id = null; } + node.superClass = this.eat(acorn.tokTypes._extends) ? this.parseExpression() : null; + node.body = this.startNode(); + node.body.body = []; + this.pushCx(); + var indent = this.curIndent + 1, line = this.curLineStart; + this.eat(acorn.tokTypes.braceL); + if (this.curIndent + 1 < indent) { indent = this.curIndent; line = this.curLineStart; } + while (!this.closes(acorn.tokTypes.braceR, indent, line)) { + var element = this.parseClassElement(); + if (element) { node.body.body.push(element); } + } + this.popCx(); + if (!this.eat(acorn.tokTypes.braceR)) { + // If there is no closing brace, make the node span to the start + // of the next token (this is useful for Tern) + this.last.end = this.tok.start; + if (this.options.locations) { this.last.loc.end = this.tok.loc.start; } + } + this.semicolon(); + this.finishNode(node.body, "ClassBody"); + return this.finishNode(node, isStatement ? "ClassDeclaration" : "ClassExpression") + }; + + lp$1.parseClassElement = function() { + if (this.eat(acorn.tokTypes.semi)) { return null } + + var ref = this.options; + var ecmaVersion = ref.ecmaVersion; + var locations = ref.locations; + var indent = this.curIndent; + var line = this.curLineStart; + var node = this.startNode(); + var keyName = ""; + var isGenerator = false; + var isAsync = false; + var kind = "method"; + var isStatic = false; + + if (this.eatContextual("static")) { + // Parse static init block + if (ecmaVersion >= 13 && this.eat(acorn.tokTypes.braceL)) { + this.parseClassStaticBlock(node); + return node + } + if (this.isClassElementNameStart() || this.toks.type === acorn.tokTypes.star) { + isStatic = true; + } else { + keyName = "static"; + } + } + node.static = isStatic; + if (!keyName && ecmaVersion >= 8 && this.eatContextual("async")) { + if ((this.isClassElementNameStart() || this.toks.type === acorn.tokTypes.star) && !this.canInsertSemicolon()) { + isAsync = true; + } else { + keyName = "async"; + } + } + if (!keyName) { + isGenerator = this.eat(acorn.tokTypes.star); + var lastValue = this.toks.value; + if (this.eatContextual("get") || this.eatContextual("set")) { + if (this.isClassElementNameStart()) { + kind = lastValue; + } else { + keyName = lastValue; + } + } + } + + // Parse element name + if (keyName) { + // 'async', 'get', 'set', or 'static' were not a keyword contextually. + // The last token is any of those. Make it the element name. + node.computed = false; + node.key = this.startNodeAt(locations ? [this.toks.lastTokStart, this.toks.lastTokStartLoc] : this.toks.lastTokStart); + node.key.name = keyName; + this.finishNode(node.key, "Identifier"); + } else { + this.parseClassElementName(node); + + // From https://github.com/acornjs/acorn/blob/7deba41118d6384a2c498c61176b3cf434f69590/acorn-loose/src/statement.js#L291 + // Skip broken stuff. + if (isDummy(node.key)) { + if (isDummy(this.parseMaybeAssign())) { this.next(); } + this.eat(acorn.tokTypes.comma); + return null + } + } + + // Parse element value + if (ecmaVersion < 13 || this.toks.type === acorn.tokTypes.parenL || kind !== "method" || isGenerator || isAsync) { + // Method + var isConstructor = + !node.computed && + !node.static && + !isGenerator && + !isAsync && + kind === "method" && ( + node.key.type === "Identifier" && node.key.name === "constructor" || + node.key.type === "Literal" && node.key.value === "constructor" + ); + node.kind = isConstructor ? "constructor" : kind; + node.value = this.parseMethod(isGenerator, isAsync); + this.finishNode(node, "MethodDefinition"); + } else { + // Field + if (this.eat(acorn.tokTypes.eq)) { + if (this.curLineStart !== line && this.curIndent <= indent && this.tokenStartsLine()) { + // Estimated the next line is the next class element by indentations. + node.value = null; + } else { + var oldInAsync = this.inAsync; + var oldInGenerator = this.inGenerator; + this.inAsync = false; + this.inGenerator = false; + node.value = this.parseMaybeAssign(); + this.inAsync = oldInAsync; + this.inGenerator = oldInGenerator; + } + } else { + node.value = null; + } + this.semicolon(); + this.finishNode(node, "PropertyDefinition"); + } + + return node + }; + + lp$1.parseClassStaticBlock = function(node) { + var blockIndent = this.curIndent, line = this.curLineStart; + node.body = []; + this.pushCx(); + while (!this.closes(acorn.tokTypes.braceR, blockIndent, line, true)) + { node.body.push(this.parseStatement()); } + this.popCx(); + this.eat(acorn.tokTypes.braceR); + + return this.finishNode(node, "StaticBlock") + }; + + lp$1.isClassElementNameStart = function() { + return this.toks.isClassElementNameStart() + }; + + lp$1.parseClassElementName = function(element) { + if (this.toks.type === acorn.tokTypes.privateId) { + element.computed = false; + element.key = this.parsePrivateIdent(); + } else { + this.parsePropertyName(element); + } + }; + + lp$1.parseFunction = function(node, isStatement, isAsync) { + var oldInAsync = this.inAsync, oldInGenerator = this.inGenerator, oldInFunction = this.inFunction; + this.initFunction(node); + if (this.options.ecmaVersion >= 6) { + node.generator = this.eat(acorn.tokTypes.star); + } + if (this.options.ecmaVersion >= 8) { + node.async = !!isAsync; + } + if (this.tok.type === acorn.tokTypes.name) { node.id = this.parseIdent(); } + else if (isStatement === true) { node.id = this.dummyIdent(); } + this.inAsync = node.async; + this.inGenerator = node.generator; + this.inFunction = true; + node.params = this.parseFunctionParams(); + node.body = this.parseBlock(); + this.toks.adaptDirectivePrologue(node.body.body); + this.inAsync = oldInAsync; + this.inGenerator = oldInGenerator; + this.inFunction = oldInFunction; + return this.finishNode(node, isStatement ? "FunctionDeclaration" : "FunctionExpression") + }; + + lp$1.parseExport = function() { + var node = this.startNode(); + this.next(); + if (this.eat(acorn.tokTypes.star)) { + if (this.options.ecmaVersion >= 11) { + if (this.eatContextual("as")) { + node.exported = this.parseExprAtom(); + } else { + node.exported = null; + } + } + node.source = this.eatContextual("from") ? this.parseExprAtom() : this.dummyString(); + if (this.options.ecmaVersion >= 16) + { node.attributes = this.parseWithClause(); } + this.semicolon(); + return this.finishNode(node, "ExportAllDeclaration") + } + if (this.eat(acorn.tokTypes._default)) { + // export default (function foo() {}) // This is FunctionExpression. + var isAsync; + if (this.tok.type === acorn.tokTypes._function || (isAsync = this.toks.isAsyncFunction())) { + var fNode = this.startNode(); + this.next(); + if (isAsync) { this.next(); } + node.declaration = this.parseFunction(fNode, "nullableID", isAsync); + } else if (this.tok.type === acorn.tokTypes._class) { + node.declaration = this.parseClass("nullableID"); + } else { + node.declaration = this.parseMaybeAssign(); + this.semicolon(); + } + return this.finishNode(node, "ExportDefaultDeclaration") + } + if (this.tok.type.keyword || this.toks.isLet() || this.toks.isAsyncFunction()) { + node.declaration = this.parseStatement(); + node.specifiers = []; + node.source = null; + } else { + node.declaration = null; + node.specifiers = this.parseExportSpecifierList(); + node.source = this.eatContextual("from") ? this.parseExprAtom() : null; + if (this.options.ecmaVersion >= 16) + { node.attributes = this.parseWithClause(); } + this.semicolon(); + } + return this.finishNode(node, "ExportNamedDeclaration") + }; + + lp$1.parseImport = function() { + var node = this.startNode(); + this.next(); + if (this.tok.type === acorn.tokTypes.string) { + node.specifiers = []; + node.source = this.parseExprAtom(); + } else { + var elt; + if (this.tok.type === acorn.tokTypes.name && this.tok.value !== "from") { + elt = this.startNode(); + elt.local = this.parseIdent(); + this.finishNode(elt, "ImportDefaultSpecifier"); + this.eat(acorn.tokTypes.comma); + } + node.specifiers = this.parseImportSpecifiers(); + node.source = this.eatContextual("from") && this.tok.type === acorn.tokTypes.string ? this.parseExprAtom() : this.dummyString(); + if (elt) { node.specifiers.unshift(elt); } + } + if (this.options.ecmaVersion >= 16) + { node.attributes = this.parseWithClause(); } + this.semicolon(); + return this.finishNode(node, "ImportDeclaration") + }; + + lp$1.parseImportSpecifiers = function() { + var elts = []; + if (this.tok.type === acorn.tokTypes.star) { + var elt = this.startNode(); + this.next(); + elt.local = this.eatContextual("as") ? this.parseIdent() : this.dummyIdent(); + elts.push(this.finishNode(elt, "ImportNamespaceSpecifier")); + } else { + var indent = this.curIndent, line = this.curLineStart, continuedLine = this.nextLineStart; + this.pushCx(); + this.eat(acorn.tokTypes.braceL); + if (this.curLineStart > continuedLine) { continuedLine = this.curLineStart; } + while (!this.closes(acorn.tokTypes.braceR, indent + (this.curLineStart <= continuedLine ? 1 : 0), line)) { + var elt$1 = this.startNode(); + if (this.eat(acorn.tokTypes.star)) { + elt$1.local = this.eatContextual("as") ? this.parseModuleExportName() : this.dummyIdent(); + this.finishNode(elt$1, "ImportNamespaceSpecifier"); + } else { + if (this.isContextual("from")) { break } + elt$1.imported = this.parseModuleExportName(); + if (isDummy(elt$1.imported)) { break } + elt$1.local = this.eatContextual("as") ? this.parseModuleExportName() : elt$1.imported; + this.finishNode(elt$1, "ImportSpecifier"); + } + elts.push(elt$1); + this.eat(acorn.tokTypes.comma); + } + this.eat(acorn.tokTypes.braceR); + this.popCx(); + } + return elts + }; + + lp$1.parseWithClause = function() { + var nodes = []; + if (!this.eat(acorn.tokTypes._with)) { + return nodes + } + + var indent = this.curIndent, line = this.curLineStart, continuedLine = this.nextLineStart; + this.pushCx(); + this.eat(acorn.tokTypes.braceL); + if (this.curLineStart > continuedLine) { continuedLine = this.curLineStart; } + while (!this.closes(acorn.tokTypes.braceR, indent + (this.curLineStart <= continuedLine ? 1 : 0), line)) { + var attr = this.startNode(); + attr.key = this.tok.type === acorn.tokTypes.string ? this.parseExprAtom() : this.parseIdent(); + if (this.eat(acorn.tokTypes.colon)) { + if (this.tok.type === acorn.tokTypes.string) + { attr.value = this.parseExprAtom(); } + else { attr.value = this.dummyString(); } + } else { + if (isDummy(attr.key)) { break } + if (this.tok.type === acorn.tokTypes.string) + { attr.value = this.parseExprAtom(); } + else { break } + } + nodes.push(this.finishNode(attr, "ImportAttribute")); + this.eat(acorn.tokTypes.comma); + } + this.eat(acorn.tokTypes.braceR); + this.popCx(); + return nodes + }; + + lp$1.parseExportSpecifierList = function() { + var elts = []; + var indent = this.curIndent, line = this.curLineStart, continuedLine = this.nextLineStart; + this.pushCx(); + this.eat(acorn.tokTypes.braceL); + if (this.curLineStart > continuedLine) { continuedLine = this.curLineStart; } + while (!this.closes(acorn.tokTypes.braceR, indent + (this.curLineStart <= continuedLine ? 1 : 0), line)) { + if (this.isContextual("from")) { break } + var elt = this.startNode(); + elt.local = this.parseModuleExportName(); + if (isDummy(elt.local)) { break } + elt.exported = this.eatContextual("as") ? this.parseModuleExportName() : elt.local; + this.finishNode(elt, "ExportSpecifier"); + elts.push(elt); + this.eat(acorn.tokTypes.comma); + } + this.eat(acorn.tokTypes.braceR); + this.popCx(); + return elts + }; + + lp$1.parseModuleExportName = function() { + return this.options.ecmaVersion >= 13 && this.tok.type === acorn.tokTypes.string + ? this.parseExprAtom() + : this.parseIdent() + }; + + var lp = LooseParser.prototype; + + lp.checkLVal = function(expr) { + if (!expr) { return expr } + switch (expr.type) { + case "Identifier": + case "MemberExpression": + return expr + + case "ParenthesizedExpression": + expr.expression = this.checkLVal(expr.expression); + return expr + + default: + return this.dummyIdent() + } + }; + + lp.parseExpression = function(noIn) { + var start = this.storeCurrentPos(); + var expr = this.parseMaybeAssign(noIn); + if (this.tok.type === acorn.tokTypes.comma) { + var node = this.startNodeAt(start); + node.expressions = [expr]; + while (this.eat(acorn.tokTypes.comma)) { node.expressions.push(this.parseMaybeAssign(noIn)); } + return this.finishNode(node, "SequenceExpression") + } + return expr + }; + + lp.parseParenExpression = function() { + this.pushCx(); + this.expect(acorn.tokTypes.parenL); + var val = this.parseExpression(); + this.popCx(); + this.expect(acorn.tokTypes.parenR); + return val + }; + + lp.parseMaybeAssign = function(noIn) { + // `yield` should be an identifier reference if it's not in generator functions. + if (this.inGenerator && this.toks.isContextual("yield")) { + var node = this.startNode(); + this.next(); + if (this.semicolon() || this.canInsertSemicolon() || (this.tok.type !== acorn.tokTypes.star && !this.tok.type.startsExpr)) { + node.delegate = false; + node.argument = null; + } else { + node.delegate = this.eat(acorn.tokTypes.star); + node.argument = this.parseMaybeAssign(); + } + return this.finishNode(node, "YieldExpression") + } + + var start = this.storeCurrentPos(); + var left = this.parseMaybeConditional(noIn); + if (this.tok.type.isAssign) { + var node$1 = this.startNodeAt(start); + node$1.operator = this.tok.value; + node$1.left = this.tok.type === acorn.tokTypes.eq ? this.toAssignable(left) : this.checkLVal(left); + this.next(); + node$1.right = this.parseMaybeAssign(noIn); + return this.finishNode(node$1, "AssignmentExpression") + } + return left + }; + + lp.parseMaybeConditional = function(noIn) { + var start = this.storeCurrentPos(); + var expr = this.parseExprOps(noIn); + if (this.eat(acorn.tokTypes.question)) { + var node = this.startNodeAt(start); + node.test = expr; + node.consequent = this.parseMaybeAssign(); + node.alternate = this.expect(acorn.tokTypes.colon) ? this.parseMaybeAssign(noIn) : this.dummyIdent(); + return this.finishNode(node, "ConditionalExpression") + } + return expr + }; + + lp.parseExprOps = function(noIn) { + var start = this.storeCurrentPos(); + var indent = this.curIndent, line = this.curLineStart; + return this.parseExprOp(this.parseMaybeUnary(false), start, -1, noIn, indent, line) + }; + + lp.parseExprOp = function(left, start, minPrec, noIn, indent, line) { + if (this.curLineStart !== line && this.curIndent < indent && this.tokenStartsLine()) { return left } + var prec = this.tok.type.binop; + if (prec != null && (!noIn || this.tok.type !== acorn.tokTypes._in)) { + if (prec > minPrec) { + var node = this.startNodeAt(start); + node.left = left; + node.operator = this.tok.value; + this.next(); + if (this.curLineStart !== line && this.curIndent < indent && this.tokenStartsLine()) { + node.right = this.dummyIdent(); + } else { + var rightStart = this.storeCurrentPos(); + node.right = this.parseExprOp(this.parseMaybeUnary(false), rightStart, prec, noIn, indent, line); + } + this.finishNode(node, /&&|\|\||\?\?/.test(node.operator) ? "LogicalExpression" : "BinaryExpression"); + return this.parseExprOp(node, start, minPrec, noIn, indent, line) + } + } + return left + }; + + lp.parseMaybeUnary = function(sawUnary) { + var start = this.storeCurrentPos(), expr; + if (this.options.ecmaVersion >= 8 && this.toks.isContextual("await") && + (this.inAsync || (this.toks.inModule && this.options.ecmaVersion >= 13) || + (!this.inFunction && this.options.allowAwaitOutsideFunction))) { + expr = this.parseAwait(); + sawUnary = true; + } else if (this.tok.type.prefix) { + var node = this.startNode(), update = this.tok.type === acorn.tokTypes.incDec; + if (!update) { sawUnary = true; } + node.operator = this.tok.value; + node.prefix = true; + this.next(); + node.argument = this.parseMaybeUnary(true); + if (update) { node.argument = this.checkLVal(node.argument); } + expr = this.finishNode(node, update ? "UpdateExpression" : "UnaryExpression"); + } else if (this.tok.type === acorn.tokTypes.ellipsis) { + var node$1 = this.startNode(); + this.next(); + node$1.argument = this.parseMaybeUnary(sawUnary); + expr = this.finishNode(node$1, "SpreadElement"); + } else if (!sawUnary && this.tok.type === acorn.tokTypes.privateId) { + expr = this.parsePrivateIdent(); + } else { + expr = this.parseExprSubscripts(); + while (this.tok.type.postfix && !this.canInsertSemicolon()) { + var node$2 = this.startNodeAt(start); + node$2.operator = this.tok.value; + node$2.prefix = false; + node$2.argument = this.checkLVal(expr); + this.next(); + expr = this.finishNode(node$2, "UpdateExpression"); + } + } + + if (!sawUnary && this.eat(acorn.tokTypes.starstar)) { + var node$3 = this.startNodeAt(start); + node$3.operator = "**"; + node$3.left = expr; + node$3.right = this.parseMaybeUnary(false); + return this.finishNode(node$3, "BinaryExpression") + } + + return expr + }; + + lp.parseExprSubscripts = function() { + var start = this.storeCurrentPos(); + return this.parseSubscripts(this.parseExprAtom(), start, false, this.curIndent, this.curLineStart) + }; + + lp.parseSubscripts = function(base, start, noCalls, startIndent, line) { + var optionalSupported = this.options.ecmaVersion >= 11; + var optionalChained = false; + for (;;) { + if (this.curLineStart !== line && this.curIndent <= startIndent && this.tokenStartsLine()) { + if (this.tok.type === acorn.tokTypes.dot && this.curIndent === startIndent) + { --startIndent; } + else + { break } + } + + var maybeAsyncArrow = base.type === "Identifier" && base.name === "async" && !this.canInsertSemicolon(); + var optional = optionalSupported && this.eat(acorn.tokTypes.questionDot); + if (optional) { + optionalChained = true; + } + + if ((optional && this.tok.type !== acorn.tokTypes.parenL && this.tok.type !== acorn.tokTypes.bracketL && this.tok.type !== acorn.tokTypes.backQuote) || this.eat(acorn.tokTypes.dot)) { + var node = this.startNodeAt(start); + node.object = base; + if (this.curLineStart !== line && this.curIndent <= startIndent && this.tokenStartsLine()) + { node.property = this.dummyIdent(); } + else + { node.property = this.parsePropertyAccessor() || this.dummyIdent(); } + node.computed = false; + if (optionalSupported) { + node.optional = optional; + } + base = this.finishNode(node, "MemberExpression"); + } else if (this.tok.type === acorn.tokTypes.bracketL) { + this.pushCx(); + this.next(); + var node$1 = this.startNodeAt(start); + node$1.object = base; + node$1.property = this.parseExpression(); + node$1.computed = true; + if (optionalSupported) { + node$1.optional = optional; + } + this.popCx(); + this.expect(acorn.tokTypes.bracketR); + base = this.finishNode(node$1, "MemberExpression"); + } else if (!noCalls && this.tok.type === acorn.tokTypes.parenL) { + var exprList = this.parseExprList(acorn.tokTypes.parenR); + if (maybeAsyncArrow && this.eat(acorn.tokTypes.arrow)) + { return this.parseArrowExpression(this.startNodeAt(start), exprList, true) } + var node$2 = this.startNodeAt(start); + node$2.callee = base; + node$2.arguments = exprList; + if (optionalSupported) { + node$2.optional = optional; + } + base = this.finishNode(node$2, "CallExpression"); + } else if (this.tok.type === acorn.tokTypes.backQuote) { + var node$3 = this.startNodeAt(start); + node$3.tag = base; + node$3.quasi = this.parseTemplate(); + base = this.finishNode(node$3, "TaggedTemplateExpression"); + } else { + break + } + } + + if (optionalChained) { + var chainNode = this.startNodeAt(start); + chainNode.expression = base; + base = this.finishNode(chainNode, "ChainExpression"); + } + return base + }; + + lp.parseExprAtom = function() { + var node; + switch (this.tok.type) { + case acorn.tokTypes._this: + case acorn.tokTypes._super: + var type = this.tok.type === acorn.tokTypes._this ? "ThisExpression" : "Super"; + node = this.startNode(); + this.next(); + return this.finishNode(node, type) + + case acorn.tokTypes.name: + var start = this.storeCurrentPos(); + var id = this.parseIdent(); + var isAsync = false; + if (id.name === "async" && !this.canInsertSemicolon()) { + if (this.eat(acorn.tokTypes._function)) { + this.toks.overrideContext(acorn.tokContexts.f_expr); + return this.parseFunction(this.startNodeAt(start), false, true) + } + if (this.tok.type === acorn.tokTypes.name) { + id = this.parseIdent(); + isAsync = true; + } + } + return this.eat(acorn.tokTypes.arrow) ? this.parseArrowExpression(this.startNodeAt(start), [id], isAsync) : id + + case acorn.tokTypes.regexp: + node = this.startNode(); + var val = this.tok.value; + node.regex = {pattern: val.pattern, flags: val.flags}; + node.value = val.value; + node.raw = this.input.slice(this.tok.start, this.tok.end); + this.next(); + return this.finishNode(node, "Literal") + + case acorn.tokTypes.num: case acorn.tokTypes.string: + node = this.startNode(); + node.value = this.tok.value; + node.raw = this.input.slice(this.tok.start, this.tok.end); + if (this.tok.type === acorn.tokTypes.num && node.raw.charCodeAt(node.raw.length - 1) === 110) + { node.bigint = node.value != null ? node.value.toString() : node.raw.slice(0, -1).replace(/_/g, ""); } + this.next(); + return this.finishNode(node, "Literal") + + case acorn.tokTypes._null: case acorn.tokTypes._true: case acorn.tokTypes._false: + node = this.startNode(); + node.value = this.tok.type === acorn.tokTypes._null ? null : this.tok.type === acorn.tokTypes._true; + node.raw = this.tok.type.keyword; + this.next(); + return this.finishNode(node, "Literal") + + case acorn.tokTypes.parenL: + var parenStart = this.storeCurrentPos(); + this.next(); + var inner = this.parseExpression(); + this.expect(acorn.tokTypes.parenR); + if (this.eat(acorn.tokTypes.arrow)) { + // (a,)=>a // SequenceExpression makes dummy in the last hole. Drop the dummy. + var params = inner.expressions || [inner]; + if (params.length && isDummy(params[params.length - 1])) + { params.pop(); } + return this.parseArrowExpression(this.startNodeAt(parenStart), params) + } + if (this.options.preserveParens) { + var par = this.startNodeAt(parenStart); + par.expression = inner; + inner = this.finishNode(par, "ParenthesizedExpression"); + } + return inner + + case acorn.tokTypes.bracketL: + node = this.startNode(); + node.elements = this.parseExprList(acorn.tokTypes.bracketR, true); + return this.finishNode(node, "ArrayExpression") + + case acorn.tokTypes.braceL: + this.toks.overrideContext(acorn.tokContexts.b_expr); + return this.parseObj() + + case acorn.tokTypes._class: + return this.parseClass(false) + + case acorn.tokTypes._function: + node = this.startNode(); + this.next(); + return this.parseFunction(node, false) + + case acorn.tokTypes._new: + return this.parseNew() + + case acorn.tokTypes.backQuote: + return this.parseTemplate() + + case acorn.tokTypes._import: + if (this.options.ecmaVersion >= 11) { + return this.parseExprImport() + } else { + return this.dummyIdent() + } + + default: + return this.dummyIdent() + } + }; + + lp.parseExprImport = function() { + var node = this.startNode(); + var meta = this.parseIdent(true); + switch (this.tok.type) { + case acorn.tokTypes.parenL: + return this.parseDynamicImport(node) + case acorn.tokTypes.dot: + node.meta = meta; + return this.parseImportMeta(node) + default: + node.name = "import"; + return this.finishNode(node, "Identifier") + } + }; + + lp.parseDynamicImport = function(node) { + var list = this.parseExprList(acorn.tokTypes.parenR); + node.source = list[0] || this.dummyString(); + node.options = list[1] || null; + return this.finishNode(node, "ImportExpression") + }; + + lp.parseImportMeta = function(node) { + this.next(); // skip '.' + node.property = this.parseIdent(true); + return this.finishNode(node, "MetaProperty") + }; + + lp.parseNew = function() { + var node = this.startNode(), startIndent = this.curIndent, line = this.curLineStart; + var meta = this.parseIdent(true); + if (this.options.ecmaVersion >= 6 && this.eat(acorn.tokTypes.dot)) { + node.meta = meta; + node.property = this.parseIdent(true); + return this.finishNode(node, "MetaProperty") + } + var start = this.storeCurrentPos(); + node.callee = this.parseSubscripts(this.parseExprAtom(), start, true, startIndent, line); + if (this.tok.type === acorn.tokTypes.parenL) { + node.arguments = this.parseExprList(acorn.tokTypes.parenR); + } else { + node.arguments = []; + } + return this.finishNode(node, "NewExpression") + }; + + lp.parseTemplateElement = function() { + var elem = this.startNode(); + + // The loose parser accepts invalid unicode escapes even in untagged templates. + if (this.tok.type === acorn.tokTypes.invalidTemplate) { + elem.value = { + raw: this.tok.value, + cooked: null + }; + } else { + elem.value = { + raw: this.input.slice(this.tok.start, this.tok.end).replace(/\r\n?/g, "\n"), + cooked: this.tok.value + }; + } + this.next(); + elem.tail = this.tok.type === acorn.tokTypes.backQuote; + return this.finishNode(elem, "TemplateElement") + }; + + lp.parseTemplate = function() { + var node = this.startNode(); + this.next(); + node.expressions = []; + var curElt = this.parseTemplateElement(); + node.quasis = [curElt]; + while (!curElt.tail) { + this.next(); + node.expressions.push(this.parseExpression()); + if (this.expect(acorn.tokTypes.braceR)) { + curElt = this.parseTemplateElement(); + } else { + curElt = this.startNode(); + curElt.value = {cooked: "", raw: ""}; + curElt.tail = true; + this.finishNode(curElt, "TemplateElement"); + } + node.quasis.push(curElt); + } + this.expect(acorn.tokTypes.backQuote); + return this.finishNode(node, "TemplateLiteral") + }; + + lp.parseObj = function() { + var node = this.startNode(); + node.properties = []; + this.pushCx(); + var indent = this.curIndent + 1, line = this.curLineStart; + this.eat(acorn.tokTypes.braceL); + if (this.curIndent + 1 < indent) { indent = this.curIndent; line = this.curLineStart; } + while (!this.closes(acorn.tokTypes.braceR, indent, line)) { + var prop = this.startNode(), isGenerator = (void 0), isAsync = (void 0), start = (void 0); + if (this.options.ecmaVersion >= 9 && this.eat(acorn.tokTypes.ellipsis)) { + prop.argument = this.parseMaybeAssign(); + node.properties.push(this.finishNode(prop, "SpreadElement")); + this.eat(acorn.tokTypes.comma); + continue + } + if (this.options.ecmaVersion >= 6) { + start = this.storeCurrentPos(); + prop.method = false; + prop.shorthand = false; + isGenerator = this.eat(acorn.tokTypes.star); + } + this.parsePropertyName(prop); + if (this.toks.isAsyncProp(prop)) { + isAsync = true; + isGenerator = this.options.ecmaVersion >= 9 && this.eat(acorn.tokTypes.star); + this.parsePropertyName(prop); + } else { + isAsync = false; + } + if (isDummy(prop.key)) { if (isDummy(this.parseMaybeAssign())) { this.next(); } this.eat(acorn.tokTypes.comma); continue } + if (this.eat(acorn.tokTypes.colon)) { + prop.kind = "init"; + prop.value = this.parseMaybeAssign(); + } else if (this.options.ecmaVersion >= 6 && (this.tok.type === acorn.tokTypes.parenL || this.tok.type === acorn.tokTypes.braceL)) { + prop.kind = "init"; + prop.method = true; + prop.value = this.parseMethod(isGenerator, isAsync); + } else if (this.options.ecmaVersion >= 5 && prop.key.type === "Identifier" && + !prop.computed && (prop.key.name === "get" || prop.key.name === "set") && + (this.tok.type !== acorn.tokTypes.comma && this.tok.type !== acorn.tokTypes.braceR && this.tok.type !== acorn.tokTypes.eq)) { + prop.kind = prop.key.name; + this.parsePropertyName(prop); + prop.value = this.parseMethod(false); + } else { + prop.kind = "init"; + if (this.options.ecmaVersion >= 6) { + if (this.eat(acorn.tokTypes.eq)) { + var assign = this.startNodeAt(start); + assign.operator = "="; + assign.left = prop.key; + assign.right = this.parseMaybeAssign(); + prop.value = this.finishNode(assign, "AssignmentExpression"); + } else { + prop.value = prop.key; + } + } else { + prop.value = this.dummyIdent(); + } + prop.shorthand = true; + } + node.properties.push(this.finishNode(prop, "Property")); + this.eat(acorn.tokTypes.comma); + } + this.popCx(); + if (!this.eat(acorn.tokTypes.braceR)) { + // If there is no closing brace, make the node span to the start + // of the next token (this is useful for Tern) + this.last.end = this.tok.start; + if (this.options.locations) { this.last.loc.end = this.tok.loc.start; } + } + return this.finishNode(node, "ObjectExpression") + }; + + lp.parsePropertyName = function(prop) { + if (this.options.ecmaVersion >= 6) { + if (this.eat(acorn.tokTypes.bracketL)) { + prop.computed = true; + prop.key = this.parseExpression(); + this.expect(acorn.tokTypes.bracketR); + return + } else { + prop.computed = false; + } + } + var key = (this.tok.type === acorn.tokTypes.num || this.tok.type === acorn.tokTypes.string) ? this.parseExprAtom() : this.parseIdent(); + prop.key = key || this.dummyIdent(); + }; + + lp.parsePropertyAccessor = function() { + if (this.tok.type === acorn.tokTypes.name || this.tok.type.keyword) { return this.parseIdent() } + if (this.tok.type === acorn.tokTypes.privateId) { return this.parsePrivateIdent() } + }; + + lp.parseIdent = function() { + var name = this.tok.type === acorn.tokTypes.name ? this.tok.value : this.tok.type.keyword; + if (!name) { return this.dummyIdent() } + if (this.tok.type.keyword) { this.toks.type = acorn.tokTypes.name; } + var node = this.startNode(); + this.next(); + node.name = name; + return this.finishNode(node, "Identifier") + }; + + lp.parsePrivateIdent = function() { + var node = this.startNode(); + node.name = this.tok.value; + this.next(); + return this.finishNode(node, "PrivateIdentifier") + }; + + lp.initFunction = function(node) { + node.id = null; + node.params = []; + if (this.options.ecmaVersion >= 6) { + node.generator = false; + node.expression = false; + } + if (this.options.ecmaVersion >= 8) + { node.async = false; } + }; + + // Convert existing expression atom to assignable pattern + // if possible. + + lp.toAssignable = function(node, binding) { + if (!node || node.type === "Identifier" || (node.type === "MemberExpression" && !binding)) ; else if (node.type === "ParenthesizedExpression") { + this.toAssignable(node.expression, binding); + } else if (this.options.ecmaVersion < 6) { + return this.dummyIdent() + } else if (node.type === "ObjectExpression") { + node.type = "ObjectPattern"; + for (var i = 0, list = node.properties; i < list.length; i += 1) + { + var prop = list[i]; + + this.toAssignable(prop, binding); + } + } else if (node.type === "ArrayExpression") { + node.type = "ArrayPattern"; + this.toAssignableList(node.elements, binding); + } else if (node.type === "Property") { + this.toAssignable(node.value, binding); + } else if (node.type === "SpreadElement") { + node.type = "RestElement"; + this.toAssignable(node.argument, binding); + } else if (node.type === "AssignmentExpression") { + node.type = "AssignmentPattern"; + delete node.operator; + } else { + return this.dummyIdent() + } + return node + }; + + lp.toAssignableList = function(exprList, binding) { + for (var i = 0, list = exprList; i < list.length; i += 1) + { + var expr = list[i]; + + this.toAssignable(expr, binding); + } + return exprList + }; + + lp.parseFunctionParams = function(params) { + params = this.parseExprList(acorn.tokTypes.parenR); + return this.toAssignableList(params, true) + }; + + lp.parseMethod = function(isGenerator, isAsync) { + var node = this.startNode(), oldInAsync = this.inAsync, oldInGenerator = this.inGenerator, oldInFunction = this.inFunction; + this.initFunction(node); + if (this.options.ecmaVersion >= 6) + { node.generator = !!isGenerator; } + if (this.options.ecmaVersion >= 8) + { node.async = !!isAsync; } + this.inAsync = node.async; + this.inGenerator = node.generator; + this.inFunction = true; + node.params = this.parseFunctionParams(); + node.body = this.parseBlock(); + this.toks.adaptDirectivePrologue(node.body.body); + this.inAsync = oldInAsync; + this.inGenerator = oldInGenerator; + this.inFunction = oldInFunction; + return this.finishNode(node, "FunctionExpression") + }; + + lp.parseArrowExpression = function(node, params, isAsync) { + var oldInAsync = this.inAsync, oldInGenerator = this.inGenerator, oldInFunction = this.inFunction; + this.initFunction(node); + if (this.options.ecmaVersion >= 8) + { node.async = !!isAsync; } + this.inAsync = node.async; + this.inGenerator = false; + this.inFunction = true; + node.params = this.toAssignableList(params, true); + node.expression = this.tok.type !== acorn.tokTypes.braceL; + if (node.expression) { + node.body = this.parseMaybeAssign(); + } else { + node.body = this.parseBlock(); + this.toks.adaptDirectivePrologue(node.body.body); + } + this.inAsync = oldInAsync; + this.inGenerator = oldInGenerator; + this.inFunction = oldInFunction; + return this.finishNode(node, "ArrowFunctionExpression") + }; + + lp.parseExprList = function(close, allowEmpty) { + this.pushCx(); + var indent = this.curIndent, line = this.curLineStart, elts = []; + this.next(); // Opening bracket + while (!this.closes(close, indent + 1, line)) { + if (this.eat(acorn.tokTypes.comma)) { + elts.push(allowEmpty ? null : this.dummyIdent()); + continue + } + var elt = this.parseMaybeAssign(); + if (isDummy(elt)) { + if (this.closes(close, indent, line)) { break } + this.next(); + } else { + elts.push(elt); + } + this.eat(acorn.tokTypes.comma); + } + this.popCx(); + if (!this.eat(close)) { + // If there is no closing brace, make the node span to the start + // of the next token (this is useful for Tern) + this.last.end = this.tok.start; + if (this.options.locations) { this.last.loc.end = this.tok.loc.start; } + } + return elts + }; + + lp.parseAwait = function() { + var node = this.startNode(); + this.next(); + node.argument = this.parseMaybeUnary(); + return this.finishNode(node, "AwaitExpression") + }; + + // Acorn: Loose parser + // + // This module provides an alternative parser that exposes that same + // interface as the main module's `parse` function, but will try to + // parse anything as JavaScript, repairing syntax error the best it + // can. There are circumstances in which it will raise an error and + // give up, but they are very rare. The resulting AST will be a mostly + // valid JavaScript AST (as per the [ESTree spec][estree], except + // that: + // + // - Return outside functions is allowed + // + // - Label consistency (no conflicts, break only to existing labels) + // is not enforced. + // + // - Bogus Identifier nodes with a name of `"✖"` are inserted whenever + // the parser got too confused to return anything meaningful. + // + // [estree]: https://github.com/estree/estree + // + // The expected use for this is to *first* try `acorn.parse`, and only + // if that fails switch to the loose parser. The loose parser might + // parse badly indented code incorrectly, so **don't** use it as your + // default parser. + // + // Quite a lot of acorn.js is duplicated here. The alternative was to + // add a *lot* of extra cruft to that file, making it less readable + // and slower. Copying and editing the code allowed me to make + // invasive changes and simplifications without creating a complicated + // tangle. + + + acorn.defaultOptions.tabSize = 4; + + function parse(input, options) { + return LooseParser.parse(input, options) + } + + exports.LooseParser = LooseParser; + exports.isDummy = isDummy; + exports.parse = parse; + +})); diff --git a/node_modules/acorn-loose/dist/acorn-loose.mjs b/node_modules/acorn-loose/dist/acorn-loose.mjs new file mode 100644 index 0000000..7dffe3c --- /dev/null +++ b/node_modules/acorn-loose/dist/acorn-loose.mjs @@ -0,0 +1,1630 @@ +import { tokTypes, SourceLocation, Node, lineBreak, isNewLine, Parser, Token, getLineInfo, lineBreakG, tokContexts, defaultOptions } from 'acorn'; + +var dummyValue = "✖"; + +function isDummy(node) { return node.name === dummyValue } + +function noop() {} + +var LooseParser = function LooseParser(input, options) { + if ( options === void 0 ) options = {}; + + this.toks = this.constructor.BaseParser.tokenizer(input, options); + this.options = this.toks.options; + this.input = this.toks.input; + this.tok = this.last = {type: tokTypes.eof, start: 0, end: 0}; + this.tok.validateRegExpFlags = noop; + this.tok.validateRegExpPattern = noop; + if (this.options.locations) { + var here = this.toks.curPosition(); + this.tok.loc = new SourceLocation(this.toks, here, here); + } + this.ahead = []; // Tokens ahead + this.context = []; // Indentation contexted + this.curIndent = 0; + this.curLineStart = 0; + this.nextLineStart = this.lineEnd(this.curLineStart) + 1; + this.inAsync = false; + this.inGenerator = false; + this.inFunction = false; +}; + +LooseParser.prototype.startNode = function startNode () { + return new Node(this.toks, this.tok.start, this.options.locations ? this.tok.loc.start : null) +}; + +LooseParser.prototype.storeCurrentPos = function storeCurrentPos () { + return this.options.locations ? [this.tok.start, this.tok.loc.start] : this.tok.start +}; + +LooseParser.prototype.startNodeAt = function startNodeAt (pos) { + if (this.options.locations) { + return new Node(this.toks, pos[0], pos[1]) + } else { + return new Node(this.toks, pos) + } +}; + +LooseParser.prototype.finishNode = function finishNode (node, type) { + node.type = type; + node.end = this.last.end; + if (this.options.locations) + { node.loc.end = this.last.loc.end; } + if (this.options.ranges) + { node.range[1] = this.last.end; } + return node +}; + +LooseParser.prototype.dummyNode = function dummyNode (type) { + var dummy = this.startNode(); + dummy.type = type; + dummy.end = dummy.start; + if (this.options.locations) + { dummy.loc.end = dummy.loc.start; } + if (this.options.ranges) + { dummy.range[1] = dummy.start; } + this.last = {type: tokTypes.name, start: dummy.start, end: dummy.start, loc: dummy.loc}; + return dummy +}; + +LooseParser.prototype.dummyIdent = function dummyIdent () { + var dummy = this.dummyNode("Identifier"); + dummy.name = dummyValue; + return dummy +}; + +LooseParser.prototype.dummyString = function dummyString () { + var dummy = this.dummyNode("Literal"); + dummy.value = dummy.raw = dummyValue; + return dummy +}; + +LooseParser.prototype.eat = function eat (type) { + if (this.tok.type === type) { + this.next(); + return true + } else { + return false + } +}; + +LooseParser.prototype.isContextual = function isContextual (name) { + return this.tok.type === tokTypes.name && this.tok.value === name +}; + +LooseParser.prototype.eatContextual = function eatContextual (name) { + return this.tok.value === name && this.eat(tokTypes.name) +}; + +LooseParser.prototype.canInsertSemicolon = function canInsertSemicolon () { + return this.tok.type === tokTypes.eof || this.tok.type === tokTypes.braceR || + lineBreak.test(this.input.slice(this.last.end, this.tok.start)) +}; + +LooseParser.prototype.semicolon = function semicolon () { + return this.eat(tokTypes.semi) +}; + +LooseParser.prototype.expect = function expect (type) { + if (this.eat(type)) { return true } + for (var i = 1; i <= 2; i++) { + if (this.lookAhead(i).type === type) { + for (var j = 0; j < i; j++) { this.next(); } + return true + } + } +}; + +LooseParser.prototype.pushCx = function pushCx () { + this.context.push(this.curIndent); +}; + +LooseParser.prototype.popCx = function popCx () { + this.curIndent = this.context.pop(); +}; + +LooseParser.prototype.lineEnd = function lineEnd (pos) { + while (pos < this.input.length && !isNewLine(this.input.charCodeAt(pos))) { ++pos; } + return pos +}; + +LooseParser.prototype.indentationAfter = function indentationAfter (pos) { + for (var count = 0;; ++pos) { + var ch = this.input.charCodeAt(pos); + if (ch === 32) { ++count; } + else if (ch === 9) { count += this.options.tabSize; } + else { return count } + } +}; + +LooseParser.prototype.closes = function closes (closeTok, indent, line, blockHeuristic) { + if (this.tok.type === closeTok || this.tok.type === tokTypes.eof) { return true } + return line !== this.curLineStart && this.curIndent < indent && this.tokenStartsLine() && + (!blockHeuristic || this.nextLineStart >= this.input.length || + this.indentationAfter(this.nextLineStart) < indent) +}; + +LooseParser.prototype.tokenStartsLine = function tokenStartsLine () { + for (var p = this.tok.start - 1; p >= this.curLineStart; --p) { + var ch = this.input.charCodeAt(p); + if (ch !== 9 && ch !== 32) { return false } + } + return true +}; + +LooseParser.prototype.extend = function extend (name, f) { + this[name] = f(this[name]); +}; + +LooseParser.prototype.parse = function parse () { + this.next(); + return this.parseTopLevel() +}; + +LooseParser.extend = function extend () { + var plugins = [], len = arguments.length; + while ( len-- ) plugins[ len ] = arguments[ len ]; + + var cls = this; + for (var i = 0; i < plugins.length; i++) { cls = plugins[i](cls); } + return cls +}; + +LooseParser.parse = function parse (input, options) { + return new this(input, options).parse() +}; + +// Allows plugins to extend the base parser / tokenizer used +LooseParser.BaseParser = Parser; + +var lp$2 = LooseParser.prototype; + +function isSpace(ch) { + return (ch < 14 && ch > 8) || ch === 32 || ch === 160 || isNewLine(ch) +} + +lp$2.next = function() { + this.last = this.tok; + if (this.ahead.length) + { this.tok = this.ahead.shift(); } + else + { this.tok = this.readToken(); } + + if (this.tok.start >= this.nextLineStart) { + while (this.tok.start >= this.nextLineStart) { + this.curLineStart = this.nextLineStart; + this.nextLineStart = this.lineEnd(this.curLineStart) + 1; + } + this.curIndent = this.indentationAfter(this.curLineStart); + } +}; + +lp$2.readToken = function() { + for (;;) { + try { + this.toks.next(); + if (this.toks.type === tokTypes.dot && + this.input.substr(this.toks.end, 1) === "." && + this.options.ecmaVersion >= 6) { + this.toks.end++; + this.toks.type = tokTypes.ellipsis; + } + return new Token(this.toks) + } catch (e) { + if (!(e instanceof SyntaxError)) { throw e } + + // Try to skip some text, based on the error message, and then continue + var msg = e.message, pos = e.raisedAt, replace = true; + if (/unterminated/i.test(msg)) { + pos = this.lineEnd(e.pos + 1); + if (/string/.test(msg)) { + replace = {start: e.pos, end: pos, type: tokTypes.string, value: this.input.slice(e.pos + 1, pos)}; + } else if (/regular expr/i.test(msg)) { + var re = this.input.slice(e.pos, pos); + try { re = new RegExp(re); } catch (e$1) { /* ignore compilation error due to new syntax */ } + replace = {start: e.pos, end: pos, type: tokTypes.regexp, value: re}; + } else if (/template/.test(msg)) { + replace = { + start: e.pos, + end: pos, + type: tokTypes.template, + value: this.input.slice(e.pos, pos) + }; + } else { + replace = false; + } + } else if (/invalid (unicode|regexp|number)|expecting unicode|octal literal|is reserved|directly after number|expected number in radix|numeric separator/i.test(msg)) { + while (pos < this.input.length && !isSpace(this.input.charCodeAt(pos))) { ++pos; } + } else if (/character escape|expected hexadecimal/i.test(msg)) { + while (pos < this.input.length) { + var ch = this.input.charCodeAt(pos++); + if (ch === 34 || ch === 39 || isNewLine(ch)) { break } + } + } else if (/unexpected character/i.test(msg)) { + pos++; + replace = false; + } else if (/regular expression/i.test(msg)) { + replace = true; + } else { + throw e + } + this.resetTo(pos); + if (replace === true) { replace = {start: pos, end: pos, type: tokTypes.name, value: dummyValue}; } + if (replace) { + if (this.options.locations) + { replace.loc = new SourceLocation( + this.toks, + getLineInfo(this.input, replace.start), + getLineInfo(this.input, replace.end)); } + return replace + } + } + } +}; + +lp$2.resetTo = function(pos) { + this.toks.pos = pos; + this.toks.containsEsc = false; + var ch = this.input.charAt(pos - 1); + this.toks.exprAllowed = !ch || /[[{(,;:?/*=+\-~!|&%^<>]/.test(ch) || + /[enwfd]/.test(ch) && + /\b(case|else|return|throw|new|in|(instance|type)?of|delete|void)$/.test(this.input.slice(pos - 10, pos)); + + if (this.options.locations) { + this.toks.curLine = 1; + this.toks.lineStart = lineBreakG.lastIndex = 0; + var match; + while ((match = lineBreakG.exec(this.input)) && match.index < pos) { + ++this.toks.curLine; + this.toks.lineStart = match.index + match[0].length; + } + } +}; + +lp$2.lookAhead = function(n) { + while (n > this.ahead.length) + { this.ahead.push(this.readToken()); } + return this.ahead[n - 1] +}; + +var lp$1 = LooseParser.prototype; + +lp$1.parseTopLevel = function() { + var node = this.startNodeAt(this.options.locations ? [0, getLineInfo(this.input, 0)] : 0); + node.body = []; + while (this.tok.type !== tokTypes.eof) { node.body.push(this.parseStatement()); } + this.toks.adaptDirectivePrologue(node.body); + this.last = this.tok; + node.sourceType = this.options.sourceType === "commonjs" ? "script" : this.options.sourceType; + return this.finishNode(node, "Program") +}; + +lp$1.parseStatement = function() { + var starttype = this.tok.type, node = this.startNode(), kind; + + if (this.toks.isLet()) { + starttype = tokTypes._var; + kind = "let"; + } + + switch (starttype) { + case tokTypes._break: case tokTypes._continue: + this.next(); + var isBreak = starttype === tokTypes._break; + if (this.semicolon() || this.canInsertSemicolon()) { + node.label = null; + } else { + node.label = this.tok.type === tokTypes.name ? this.parseIdent() : null; + this.semicolon(); + } + return this.finishNode(node, isBreak ? "BreakStatement" : "ContinueStatement") + + case tokTypes._debugger: + this.next(); + this.semicolon(); + return this.finishNode(node, "DebuggerStatement") + + case tokTypes._do: + this.next(); + node.body = this.parseStatement(); + node.test = this.eat(tokTypes._while) ? this.parseParenExpression() : this.dummyIdent(); + this.semicolon(); + return this.finishNode(node, "DoWhileStatement") + + case tokTypes._for: + this.next(); // `for` keyword + var isAwait = this.options.ecmaVersion >= 9 && this.eatContextual("await"); + + this.pushCx(); + this.expect(tokTypes.parenL); + if (this.tok.type === tokTypes.semi) { return this.parseFor(node, null) } + var isLet = this.toks.isLet(); + var isAwaitUsing = this.toks.isAwaitUsing(true); + var isUsing = !isAwaitUsing && this.toks.isUsing(true); + + if (isLet || this.tok.type === tokTypes._var || this.tok.type === tokTypes._const || isUsing || isAwaitUsing) { + var kind$1 = isLet ? "let" : isUsing ? "using" : isAwaitUsing ? "await using" : this.tok.value; + var init$1 = this.startNode(); + if (isUsing || isAwaitUsing) { + if (isAwaitUsing) { this.next(); } + this.parseVar(init$1, true, kind$1); + } else { + init$1 = this.parseVar(init$1, true, kind$1); + } + + if (init$1.declarations.length === 1 && (this.tok.type === tokTypes._in || this.isContextual("of"))) { + if (this.options.ecmaVersion >= 9 && this.tok.type !== tokTypes._in) { + node.await = isAwait; + } + return this.parseForIn(node, init$1) + } + return this.parseFor(node, init$1) + } + var init = this.parseExpression(true); + if (this.tok.type === tokTypes._in || this.isContextual("of")) { + if (this.options.ecmaVersion >= 9 && this.tok.type !== tokTypes._in) { + node.await = isAwait; + } + return this.parseForIn(node, this.toAssignable(init)) + } + return this.parseFor(node, init) + + case tokTypes._function: + this.next(); + return this.parseFunction(node, true) + + case tokTypes._if: + this.next(); + node.test = this.parseParenExpression(); + node.consequent = this.parseStatement(); + node.alternate = this.eat(tokTypes._else) ? this.parseStatement() : null; + return this.finishNode(node, "IfStatement") + + case tokTypes._return: + this.next(); + if (this.eat(tokTypes.semi) || this.canInsertSemicolon()) { node.argument = null; } + else { node.argument = this.parseExpression(); this.semicolon(); } + return this.finishNode(node, "ReturnStatement") + + case tokTypes._switch: + var blockIndent = this.curIndent, line = this.curLineStart; + this.next(); + node.discriminant = this.parseParenExpression(); + node.cases = []; + this.pushCx(); + this.expect(tokTypes.braceL); + + var cur; + while (!this.closes(tokTypes.braceR, blockIndent, line, true)) { + if (this.tok.type === tokTypes._case || this.tok.type === tokTypes._default) { + var isCase = this.tok.type === tokTypes._case; + if (cur) { this.finishNode(cur, "SwitchCase"); } + node.cases.push(cur = this.startNode()); + cur.consequent = []; + this.next(); + if (isCase) { cur.test = this.parseExpression(); } + else { cur.test = null; } + this.expect(tokTypes.colon); + } else { + if (!cur) { + node.cases.push(cur = this.startNode()); + cur.consequent = []; + cur.test = null; + } + cur.consequent.push(this.parseStatement()); + } + } + if (cur) { this.finishNode(cur, "SwitchCase"); } + this.popCx(); + this.eat(tokTypes.braceR); + return this.finishNode(node, "SwitchStatement") + + case tokTypes._throw: + this.next(); + node.argument = this.parseExpression(); + this.semicolon(); + return this.finishNode(node, "ThrowStatement") + + case tokTypes._try: + this.next(); + node.block = this.parseBlock(); + node.handler = null; + if (this.tok.type === tokTypes._catch) { + var clause = this.startNode(); + this.next(); + if (this.eat(tokTypes.parenL)) { + clause.param = this.toAssignable(this.parseExprAtom(), true); + this.expect(tokTypes.parenR); + } else { + clause.param = null; + } + clause.body = this.parseBlock(); + node.handler = this.finishNode(clause, "CatchClause"); + } + node.finalizer = this.eat(tokTypes._finally) ? this.parseBlock() : null; + if (!node.handler && !node.finalizer) { return node.block } + return this.finishNode(node, "TryStatement") + + case tokTypes._var: + case tokTypes._const: + return this.parseVar(node, false, kind || this.tok.value) + + case tokTypes._while: + this.next(); + node.test = this.parseParenExpression(); + node.body = this.parseStatement(); + return this.finishNode(node, "WhileStatement") + + case tokTypes._with: + this.next(); + node.object = this.parseParenExpression(); + node.body = this.parseStatement(); + return this.finishNode(node, "WithStatement") + + case tokTypes.braceL: + return this.parseBlock() + + case tokTypes.semi: + this.next(); + return this.finishNode(node, "EmptyStatement") + + case tokTypes._class: + return this.parseClass(true) + + case tokTypes._import: + if (this.options.ecmaVersion > 10) { + var nextType = this.lookAhead(1).type; + if (nextType === tokTypes.parenL || nextType === tokTypes.dot) { + node.expression = this.parseExpression(); + this.semicolon(); + return this.finishNode(node, "ExpressionStatement") + } + } + + return this.parseImport() + + case tokTypes._export: + return this.parseExport() + + default: + if (this.toks.isAsyncFunction()) { + this.next(); + this.next(); + return this.parseFunction(node, true, true) + } + + if (this.toks.isUsing(false)) { + return this.parseVar(node, false, "using") + } + + if (this.toks.isAwaitUsing(false)) { + this.next(); + return this.parseVar(node, false, "await using") + } + + var expr = this.parseExpression(); + if (isDummy(expr)) { + this.next(); + if (this.tok.type === tokTypes.eof) { return this.finishNode(node, "EmptyStatement") } + return this.parseStatement() + } else if (starttype === tokTypes.name && expr.type === "Identifier" && this.eat(tokTypes.colon)) { + node.body = this.parseStatement(); + node.label = expr; + return this.finishNode(node, "LabeledStatement") + } else { + node.expression = expr; + this.semicolon(); + return this.finishNode(node, "ExpressionStatement") + } + } +}; + +lp$1.parseBlock = function() { + var node = this.startNode(); + this.pushCx(); + this.expect(tokTypes.braceL); + var blockIndent = this.curIndent, line = this.curLineStart; + node.body = []; + while (!this.closes(tokTypes.braceR, blockIndent, line, true)) + { node.body.push(this.parseStatement()); } + this.popCx(); + this.eat(tokTypes.braceR); + return this.finishNode(node, "BlockStatement") +}; + +lp$1.parseFor = function(node, init) { + node.init = init; + node.test = node.update = null; + if (this.eat(tokTypes.semi) && this.tok.type !== tokTypes.semi) { node.test = this.parseExpression(); } + if (this.eat(tokTypes.semi) && this.tok.type !== tokTypes.parenR) { node.update = this.parseExpression(); } + this.popCx(); + this.expect(tokTypes.parenR); + node.body = this.parseStatement(); + return this.finishNode(node, "ForStatement") +}; + +lp$1.parseForIn = function(node, init) { + var type = this.tok.type === tokTypes._in ? "ForInStatement" : "ForOfStatement"; + this.next(); + node.left = init; + node.right = this.parseExpression(); + this.popCx(); + this.expect(tokTypes.parenR); + node.body = this.parseStatement(); + return this.finishNode(node, type) +}; + +lp$1.parseVar = function(node, noIn, kind) { + node.kind = kind; + this.next(); + node.declarations = []; + do { + var decl = this.startNode(); + decl.id = this.options.ecmaVersion >= 6 ? this.toAssignable(this.parseExprAtom(), true) : this.parseIdent(); + decl.init = this.eat(tokTypes.eq) ? this.parseMaybeAssign(noIn) : null; + node.declarations.push(this.finishNode(decl, "VariableDeclarator")); + } while (this.eat(tokTypes.comma)) + if (!node.declarations.length) { + var decl$1 = this.startNode(); + decl$1.id = this.dummyIdent(); + node.declarations.push(this.finishNode(decl$1, "VariableDeclarator")); + } + if (!noIn) { this.semicolon(); } + return this.finishNode(node, "VariableDeclaration") +}; + +lp$1.parseClass = function(isStatement) { + var node = this.startNode(); + this.next(); + if (this.tok.type === tokTypes.name) { node.id = this.parseIdent(); } + else if (isStatement === true) { node.id = this.dummyIdent(); } + else { node.id = null; } + node.superClass = this.eat(tokTypes._extends) ? this.parseExpression() : null; + node.body = this.startNode(); + node.body.body = []; + this.pushCx(); + var indent = this.curIndent + 1, line = this.curLineStart; + this.eat(tokTypes.braceL); + if (this.curIndent + 1 < indent) { indent = this.curIndent; line = this.curLineStart; } + while (!this.closes(tokTypes.braceR, indent, line)) { + var element = this.parseClassElement(); + if (element) { node.body.body.push(element); } + } + this.popCx(); + if (!this.eat(tokTypes.braceR)) { + // If there is no closing brace, make the node span to the start + // of the next token (this is useful for Tern) + this.last.end = this.tok.start; + if (this.options.locations) { this.last.loc.end = this.tok.loc.start; } + } + this.semicolon(); + this.finishNode(node.body, "ClassBody"); + return this.finishNode(node, isStatement ? "ClassDeclaration" : "ClassExpression") +}; + +lp$1.parseClassElement = function() { + if (this.eat(tokTypes.semi)) { return null } + + var ref = this.options; + var ecmaVersion = ref.ecmaVersion; + var locations = ref.locations; + var indent = this.curIndent; + var line = this.curLineStart; + var node = this.startNode(); + var keyName = ""; + var isGenerator = false; + var isAsync = false; + var kind = "method"; + var isStatic = false; + + if (this.eatContextual("static")) { + // Parse static init block + if (ecmaVersion >= 13 && this.eat(tokTypes.braceL)) { + this.parseClassStaticBlock(node); + return node + } + if (this.isClassElementNameStart() || this.toks.type === tokTypes.star) { + isStatic = true; + } else { + keyName = "static"; + } + } + node.static = isStatic; + if (!keyName && ecmaVersion >= 8 && this.eatContextual("async")) { + if ((this.isClassElementNameStart() || this.toks.type === tokTypes.star) && !this.canInsertSemicolon()) { + isAsync = true; + } else { + keyName = "async"; + } + } + if (!keyName) { + isGenerator = this.eat(tokTypes.star); + var lastValue = this.toks.value; + if (this.eatContextual("get") || this.eatContextual("set")) { + if (this.isClassElementNameStart()) { + kind = lastValue; + } else { + keyName = lastValue; + } + } + } + + // Parse element name + if (keyName) { + // 'async', 'get', 'set', or 'static' were not a keyword contextually. + // The last token is any of those. Make it the element name. + node.computed = false; + node.key = this.startNodeAt(locations ? [this.toks.lastTokStart, this.toks.lastTokStartLoc] : this.toks.lastTokStart); + node.key.name = keyName; + this.finishNode(node.key, "Identifier"); + } else { + this.parseClassElementName(node); + + // From https://github.com/acornjs/acorn/blob/7deba41118d6384a2c498c61176b3cf434f69590/acorn-loose/src/statement.js#L291 + // Skip broken stuff. + if (isDummy(node.key)) { + if (isDummy(this.parseMaybeAssign())) { this.next(); } + this.eat(tokTypes.comma); + return null + } + } + + // Parse element value + if (ecmaVersion < 13 || this.toks.type === tokTypes.parenL || kind !== "method" || isGenerator || isAsync) { + // Method + var isConstructor = + !node.computed && + !node.static && + !isGenerator && + !isAsync && + kind === "method" && ( + node.key.type === "Identifier" && node.key.name === "constructor" || + node.key.type === "Literal" && node.key.value === "constructor" + ); + node.kind = isConstructor ? "constructor" : kind; + node.value = this.parseMethod(isGenerator, isAsync); + this.finishNode(node, "MethodDefinition"); + } else { + // Field + if (this.eat(tokTypes.eq)) { + if (this.curLineStart !== line && this.curIndent <= indent && this.tokenStartsLine()) { + // Estimated the next line is the next class element by indentations. + node.value = null; + } else { + var oldInAsync = this.inAsync; + var oldInGenerator = this.inGenerator; + this.inAsync = false; + this.inGenerator = false; + node.value = this.parseMaybeAssign(); + this.inAsync = oldInAsync; + this.inGenerator = oldInGenerator; + } + } else { + node.value = null; + } + this.semicolon(); + this.finishNode(node, "PropertyDefinition"); + } + + return node +}; + +lp$1.parseClassStaticBlock = function(node) { + var blockIndent = this.curIndent, line = this.curLineStart; + node.body = []; + this.pushCx(); + while (!this.closes(tokTypes.braceR, blockIndent, line, true)) + { node.body.push(this.parseStatement()); } + this.popCx(); + this.eat(tokTypes.braceR); + + return this.finishNode(node, "StaticBlock") +}; + +lp$1.isClassElementNameStart = function() { + return this.toks.isClassElementNameStart() +}; + +lp$1.parseClassElementName = function(element) { + if (this.toks.type === tokTypes.privateId) { + element.computed = false; + element.key = this.parsePrivateIdent(); + } else { + this.parsePropertyName(element); + } +}; + +lp$1.parseFunction = function(node, isStatement, isAsync) { + var oldInAsync = this.inAsync, oldInGenerator = this.inGenerator, oldInFunction = this.inFunction; + this.initFunction(node); + if (this.options.ecmaVersion >= 6) { + node.generator = this.eat(tokTypes.star); + } + if (this.options.ecmaVersion >= 8) { + node.async = !!isAsync; + } + if (this.tok.type === tokTypes.name) { node.id = this.parseIdent(); } + else if (isStatement === true) { node.id = this.dummyIdent(); } + this.inAsync = node.async; + this.inGenerator = node.generator; + this.inFunction = true; + node.params = this.parseFunctionParams(); + node.body = this.parseBlock(); + this.toks.adaptDirectivePrologue(node.body.body); + this.inAsync = oldInAsync; + this.inGenerator = oldInGenerator; + this.inFunction = oldInFunction; + return this.finishNode(node, isStatement ? "FunctionDeclaration" : "FunctionExpression") +}; + +lp$1.parseExport = function() { + var node = this.startNode(); + this.next(); + if (this.eat(tokTypes.star)) { + if (this.options.ecmaVersion >= 11) { + if (this.eatContextual("as")) { + node.exported = this.parseExprAtom(); + } else { + node.exported = null; + } + } + node.source = this.eatContextual("from") ? this.parseExprAtom() : this.dummyString(); + if (this.options.ecmaVersion >= 16) + { node.attributes = this.parseWithClause(); } + this.semicolon(); + return this.finishNode(node, "ExportAllDeclaration") + } + if (this.eat(tokTypes._default)) { + // export default (function foo() {}) // This is FunctionExpression. + var isAsync; + if (this.tok.type === tokTypes._function || (isAsync = this.toks.isAsyncFunction())) { + var fNode = this.startNode(); + this.next(); + if (isAsync) { this.next(); } + node.declaration = this.parseFunction(fNode, "nullableID", isAsync); + } else if (this.tok.type === tokTypes._class) { + node.declaration = this.parseClass("nullableID"); + } else { + node.declaration = this.parseMaybeAssign(); + this.semicolon(); + } + return this.finishNode(node, "ExportDefaultDeclaration") + } + if (this.tok.type.keyword || this.toks.isLet() || this.toks.isAsyncFunction()) { + node.declaration = this.parseStatement(); + node.specifiers = []; + node.source = null; + } else { + node.declaration = null; + node.specifiers = this.parseExportSpecifierList(); + node.source = this.eatContextual("from") ? this.parseExprAtom() : null; + if (this.options.ecmaVersion >= 16) + { node.attributes = this.parseWithClause(); } + this.semicolon(); + } + return this.finishNode(node, "ExportNamedDeclaration") +}; + +lp$1.parseImport = function() { + var node = this.startNode(); + this.next(); + if (this.tok.type === tokTypes.string) { + node.specifiers = []; + node.source = this.parseExprAtom(); + } else { + var elt; + if (this.tok.type === tokTypes.name && this.tok.value !== "from") { + elt = this.startNode(); + elt.local = this.parseIdent(); + this.finishNode(elt, "ImportDefaultSpecifier"); + this.eat(tokTypes.comma); + } + node.specifiers = this.parseImportSpecifiers(); + node.source = this.eatContextual("from") && this.tok.type === tokTypes.string ? this.parseExprAtom() : this.dummyString(); + if (elt) { node.specifiers.unshift(elt); } + } + if (this.options.ecmaVersion >= 16) + { node.attributes = this.parseWithClause(); } + this.semicolon(); + return this.finishNode(node, "ImportDeclaration") +}; + +lp$1.parseImportSpecifiers = function() { + var elts = []; + if (this.tok.type === tokTypes.star) { + var elt = this.startNode(); + this.next(); + elt.local = this.eatContextual("as") ? this.parseIdent() : this.dummyIdent(); + elts.push(this.finishNode(elt, "ImportNamespaceSpecifier")); + } else { + var indent = this.curIndent, line = this.curLineStart, continuedLine = this.nextLineStart; + this.pushCx(); + this.eat(tokTypes.braceL); + if (this.curLineStart > continuedLine) { continuedLine = this.curLineStart; } + while (!this.closes(tokTypes.braceR, indent + (this.curLineStart <= continuedLine ? 1 : 0), line)) { + var elt$1 = this.startNode(); + if (this.eat(tokTypes.star)) { + elt$1.local = this.eatContextual("as") ? this.parseModuleExportName() : this.dummyIdent(); + this.finishNode(elt$1, "ImportNamespaceSpecifier"); + } else { + if (this.isContextual("from")) { break } + elt$1.imported = this.parseModuleExportName(); + if (isDummy(elt$1.imported)) { break } + elt$1.local = this.eatContextual("as") ? this.parseModuleExportName() : elt$1.imported; + this.finishNode(elt$1, "ImportSpecifier"); + } + elts.push(elt$1); + this.eat(tokTypes.comma); + } + this.eat(tokTypes.braceR); + this.popCx(); + } + return elts +}; + +lp$1.parseWithClause = function() { + var nodes = []; + if (!this.eat(tokTypes._with)) { + return nodes + } + + var indent = this.curIndent, line = this.curLineStart, continuedLine = this.nextLineStart; + this.pushCx(); + this.eat(tokTypes.braceL); + if (this.curLineStart > continuedLine) { continuedLine = this.curLineStart; } + while (!this.closes(tokTypes.braceR, indent + (this.curLineStart <= continuedLine ? 1 : 0), line)) { + var attr = this.startNode(); + attr.key = this.tok.type === tokTypes.string ? this.parseExprAtom() : this.parseIdent(); + if (this.eat(tokTypes.colon)) { + if (this.tok.type === tokTypes.string) + { attr.value = this.parseExprAtom(); } + else { attr.value = this.dummyString(); } + } else { + if (isDummy(attr.key)) { break } + if (this.tok.type === tokTypes.string) + { attr.value = this.parseExprAtom(); } + else { break } + } + nodes.push(this.finishNode(attr, "ImportAttribute")); + this.eat(tokTypes.comma); + } + this.eat(tokTypes.braceR); + this.popCx(); + return nodes +}; + +lp$1.parseExportSpecifierList = function() { + var elts = []; + var indent = this.curIndent, line = this.curLineStart, continuedLine = this.nextLineStart; + this.pushCx(); + this.eat(tokTypes.braceL); + if (this.curLineStart > continuedLine) { continuedLine = this.curLineStart; } + while (!this.closes(tokTypes.braceR, indent + (this.curLineStart <= continuedLine ? 1 : 0), line)) { + if (this.isContextual("from")) { break } + var elt = this.startNode(); + elt.local = this.parseModuleExportName(); + if (isDummy(elt.local)) { break } + elt.exported = this.eatContextual("as") ? this.parseModuleExportName() : elt.local; + this.finishNode(elt, "ExportSpecifier"); + elts.push(elt); + this.eat(tokTypes.comma); + } + this.eat(tokTypes.braceR); + this.popCx(); + return elts +}; + +lp$1.parseModuleExportName = function() { + return this.options.ecmaVersion >= 13 && this.tok.type === tokTypes.string + ? this.parseExprAtom() + : this.parseIdent() +}; + +var lp = LooseParser.prototype; + +lp.checkLVal = function(expr) { + if (!expr) { return expr } + switch (expr.type) { + case "Identifier": + case "MemberExpression": + return expr + + case "ParenthesizedExpression": + expr.expression = this.checkLVal(expr.expression); + return expr + + default: + return this.dummyIdent() + } +}; + +lp.parseExpression = function(noIn) { + var start = this.storeCurrentPos(); + var expr = this.parseMaybeAssign(noIn); + if (this.tok.type === tokTypes.comma) { + var node = this.startNodeAt(start); + node.expressions = [expr]; + while (this.eat(tokTypes.comma)) { node.expressions.push(this.parseMaybeAssign(noIn)); } + return this.finishNode(node, "SequenceExpression") + } + return expr +}; + +lp.parseParenExpression = function() { + this.pushCx(); + this.expect(tokTypes.parenL); + var val = this.parseExpression(); + this.popCx(); + this.expect(tokTypes.parenR); + return val +}; + +lp.parseMaybeAssign = function(noIn) { + // `yield` should be an identifier reference if it's not in generator functions. + if (this.inGenerator && this.toks.isContextual("yield")) { + var node = this.startNode(); + this.next(); + if (this.semicolon() || this.canInsertSemicolon() || (this.tok.type !== tokTypes.star && !this.tok.type.startsExpr)) { + node.delegate = false; + node.argument = null; + } else { + node.delegate = this.eat(tokTypes.star); + node.argument = this.parseMaybeAssign(); + } + return this.finishNode(node, "YieldExpression") + } + + var start = this.storeCurrentPos(); + var left = this.parseMaybeConditional(noIn); + if (this.tok.type.isAssign) { + var node$1 = this.startNodeAt(start); + node$1.operator = this.tok.value; + node$1.left = this.tok.type === tokTypes.eq ? this.toAssignable(left) : this.checkLVal(left); + this.next(); + node$1.right = this.parseMaybeAssign(noIn); + return this.finishNode(node$1, "AssignmentExpression") + } + return left +}; + +lp.parseMaybeConditional = function(noIn) { + var start = this.storeCurrentPos(); + var expr = this.parseExprOps(noIn); + if (this.eat(tokTypes.question)) { + var node = this.startNodeAt(start); + node.test = expr; + node.consequent = this.parseMaybeAssign(); + node.alternate = this.expect(tokTypes.colon) ? this.parseMaybeAssign(noIn) : this.dummyIdent(); + return this.finishNode(node, "ConditionalExpression") + } + return expr +}; + +lp.parseExprOps = function(noIn) { + var start = this.storeCurrentPos(); + var indent = this.curIndent, line = this.curLineStart; + return this.parseExprOp(this.parseMaybeUnary(false), start, -1, noIn, indent, line) +}; + +lp.parseExprOp = function(left, start, minPrec, noIn, indent, line) { + if (this.curLineStart !== line && this.curIndent < indent && this.tokenStartsLine()) { return left } + var prec = this.tok.type.binop; + if (prec != null && (!noIn || this.tok.type !== tokTypes._in)) { + if (prec > minPrec) { + var node = this.startNodeAt(start); + node.left = left; + node.operator = this.tok.value; + this.next(); + if (this.curLineStart !== line && this.curIndent < indent && this.tokenStartsLine()) { + node.right = this.dummyIdent(); + } else { + var rightStart = this.storeCurrentPos(); + node.right = this.parseExprOp(this.parseMaybeUnary(false), rightStart, prec, noIn, indent, line); + } + this.finishNode(node, /&&|\|\||\?\?/.test(node.operator) ? "LogicalExpression" : "BinaryExpression"); + return this.parseExprOp(node, start, minPrec, noIn, indent, line) + } + } + return left +}; + +lp.parseMaybeUnary = function(sawUnary) { + var start = this.storeCurrentPos(), expr; + if (this.options.ecmaVersion >= 8 && this.toks.isContextual("await") && + (this.inAsync || (this.toks.inModule && this.options.ecmaVersion >= 13) || + (!this.inFunction && this.options.allowAwaitOutsideFunction))) { + expr = this.parseAwait(); + sawUnary = true; + } else if (this.tok.type.prefix) { + var node = this.startNode(), update = this.tok.type === tokTypes.incDec; + if (!update) { sawUnary = true; } + node.operator = this.tok.value; + node.prefix = true; + this.next(); + node.argument = this.parseMaybeUnary(true); + if (update) { node.argument = this.checkLVal(node.argument); } + expr = this.finishNode(node, update ? "UpdateExpression" : "UnaryExpression"); + } else if (this.tok.type === tokTypes.ellipsis) { + var node$1 = this.startNode(); + this.next(); + node$1.argument = this.parseMaybeUnary(sawUnary); + expr = this.finishNode(node$1, "SpreadElement"); + } else if (!sawUnary && this.tok.type === tokTypes.privateId) { + expr = this.parsePrivateIdent(); + } else { + expr = this.parseExprSubscripts(); + while (this.tok.type.postfix && !this.canInsertSemicolon()) { + var node$2 = this.startNodeAt(start); + node$2.operator = this.tok.value; + node$2.prefix = false; + node$2.argument = this.checkLVal(expr); + this.next(); + expr = this.finishNode(node$2, "UpdateExpression"); + } + } + + if (!sawUnary && this.eat(tokTypes.starstar)) { + var node$3 = this.startNodeAt(start); + node$3.operator = "**"; + node$3.left = expr; + node$3.right = this.parseMaybeUnary(false); + return this.finishNode(node$3, "BinaryExpression") + } + + return expr +}; + +lp.parseExprSubscripts = function() { + var start = this.storeCurrentPos(); + return this.parseSubscripts(this.parseExprAtom(), start, false, this.curIndent, this.curLineStart) +}; + +lp.parseSubscripts = function(base, start, noCalls, startIndent, line) { + var optionalSupported = this.options.ecmaVersion >= 11; + var optionalChained = false; + for (;;) { + if (this.curLineStart !== line && this.curIndent <= startIndent && this.tokenStartsLine()) { + if (this.tok.type === tokTypes.dot && this.curIndent === startIndent) + { --startIndent; } + else + { break } + } + + var maybeAsyncArrow = base.type === "Identifier" && base.name === "async" && !this.canInsertSemicolon(); + var optional = optionalSupported && this.eat(tokTypes.questionDot); + if (optional) { + optionalChained = true; + } + + if ((optional && this.tok.type !== tokTypes.parenL && this.tok.type !== tokTypes.bracketL && this.tok.type !== tokTypes.backQuote) || this.eat(tokTypes.dot)) { + var node = this.startNodeAt(start); + node.object = base; + if (this.curLineStart !== line && this.curIndent <= startIndent && this.tokenStartsLine()) + { node.property = this.dummyIdent(); } + else + { node.property = this.parsePropertyAccessor() || this.dummyIdent(); } + node.computed = false; + if (optionalSupported) { + node.optional = optional; + } + base = this.finishNode(node, "MemberExpression"); + } else if (this.tok.type === tokTypes.bracketL) { + this.pushCx(); + this.next(); + var node$1 = this.startNodeAt(start); + node$1.object = base; + node$1.property = this.parseExpression(); + node$1.computed = true; + if (optionalSupported) { + node$1.optional = optional; + } + this.popCx(); + this.expect(tokTypes.bracketR); + base = this.finishNode(node$1, "MemberExpression"); + } else if (!noCalls && this.tok.type === tokTypes.parenL) { + var exprList = this.parseExprList(tokTypes.parenR); + if (maybeAsyncArrow && this.eat(tokTypes.arrow)) + { return this.parseArrowExpression(this.startNodeAt(start), exprList, true) } + var node$2 = this.startNodeAt(start); + node$2.callee = base; + node$2.arguments = exprList; + if (optionalSupported) { + node$2.optional = optional; + } + base = this.finishNode(node$2, "CallExpression"); + } else if (this.tok.type === tokTypes.backQuote) { + var node$3 = this.startNodeAt(start); + node$3.tag = base; + node$3.quasi = this.parseTemplate(); + base = this.finishNode(node$3, "TaggedTemplateExpression"); + } else { + break + } + } + + if (optionalChained) { + var chainNode = this.startNodeAt(start); + chainNode.expression = base; + base = this.finishNode(chainNode, "ChainExpression"); + } + return base +}; + +lp.parseExprAtom = function() { + var node; + switch (this.tok.type) { + case tokTypes._this: + case tokTypes._super: + var type = this.tok.type === tokTypes._this ? "ThisExpression" : "Super"; + node = this.startNode(); + this.next(); + return this.finishNode(node, type) + + case tokTypes.name: + var start = this.storeCurrentPos(); + var id = this.parseIdent(); + var isAsync = false; + if (id.name === "async" && !this.canInsertSemicolon()) { + if (this.eat(tokTypes._function)) { + this.toks.overrideContext(tokContexts.f_expr); + return this.parseFunction(this.startNodeAt(start), false, true) + } + if (this.tok.type === tokTypes.name) { + id = this.parseIdent(); + isAsync = true; + } + } + return this.eat(tokTypes.arrow) ? this.parseArrowExpression(this.startNodeAt(start), [id], isAsync) : id + + case tokTypes.regexp: + node = this.startNode(); + var val = this.tok.value; + node.regex = {pattern: val.pattern, flags: val.flags}; + node.value = val.value; + node.raw = this.input.slice(this.tok.start, this.tok.end); + this.next(); + return this.finishNode(node, "Literal") + + case tokTypes.num: case tokTypes.string: + node = this.startNode(); + node.value = this.tok.value; + node.raw = this.input.slice(this.tok.start, this.tok.end); + if (this.tok.type === tokTypes.num && node.raw.charCodeAt(node.raw.length - 1) === 110) + { node.bigint = node.value != null ? node.value.toString() : node.raw.slice(0, -1).replace(/_/g, ""); } + this.next(); + return this.finishNode(node, "Literal") + + case tokTypes._null: case tokTypes._true: case tokTypes._false: + node = this.startNode(); + node.value = this.tok.type === tokTypes._null ? null : this.tok.type === tokTypes._true; + node.raw = this.tok.type.keyword; + this.next(); + return this.finishNode(node, "Literal") + + case tokTypes.parenL: + var parenStart = this.storeCurrentPos(); + this.next(); + var inner = this.parseExpression(); + this.expect(tokTypes.parenR); + if (this.eat(tokTypes.arrow)) { + // (a,)=>a // SequenceExpression makes dummy in the last hole. Drop the dummy. + var params = inner.expressions || [inner]; + if (params.length && isDummy(params[params.length - 1])) + { params.pop(); } + return this.parseArrowExpression(this.startNodeAt(parenStart), params) + } + if (this.options.preserveParens) { + var par = this.startNodeAt(parenStart); + par.expression = inner; + inner = this.finishNode(par, "ParenthesizedExpression"); + } + return inner + + case tokTypes.bracketL: + node = this.startNode(); + node.elements = this.parseExprList(tokTypes.bracketR, true); + return this.finishNode(node, "ArrayExpression") + + case tokTypes.braceL: + this.toks.overrideContext(tokContexts.b_expr); + return this.parseObj() + + case tokTypes._class: + return this.parseClass(false) + + case tokTypes._function: + node = this.startNode(); + this.next(); + return this.parseFunction(node, false) + + case tokTypes._new: + return this.parseNew() + + case tokTypes.backQuote: + return this.parseTemplate() + + case tokTypes._import: + if (this.options.ecmaVersion >= 11) { + return this.parseExprImport() + } else { + return this.dummyIdent() + } + + default: + return this.dummyIdent() + } +}; + +lp.parseExprImport = function() { + var node = this.startNode(); + var meta = this.parseIdent(true); + switch (this.tok.type) { + case tokTypes.parenL: + return this.parseDynamicImport(node) + case tokTypes.dot: + node.meta = meta; + return this.parseImportMeta(node) + default: + node.name = "import"; + return this.finishNode(node, "Identifier") + } +}; + +lp.parseDynamicImport = function(node) { + var list = this.parseExprList(tokTypes.parenR); + node.source = list[0] || this.dummyString(); + node.options = list[1] || null; + return this.finishNode(node, "ImportExpression") +}; + +lp.parseImportMeta = function(node) { + this.next(); // skip '.' + node.property = this.parseIdent(true); + return this.finishNode(node, "MetaProperty") +}; + +lp.parseNew = function() { + var node = this.startNode(), startIndent = this.curIndent, line = this.curLineStart; + var meta = this.parseIdent(true); + if (this.options.ecmaVersion >= 6 && this.eat(tokTypes.dot)) { + node.meta = meta; + node.property = this.parseIdent(true); + return this.finishNode(node, "MetaProperty") + } + var start = this.storeCurrentPos(); + node.callee = this.parseSubscripts(this.parseExprAtom(), start, true, startIndent, line); + if (this.tok.type === tokTypes.parenL) { + node.arguments = this.parseExprList(tokTypes.parenR); + } else { + node.arguments = []; + } + return this.finishNode(node, "NewExpression") +}; + +lp.parseTemplateElement = function() { + var elem = this.startNode(); + + // The loose parser accepts invalid unicode escapes even in untagged templates. + if (this.tok.type === tokTypes.invalidTemplate) { + elem.value = { + raw: this.tok.value, + cooked: null + }; + } else { + elem.value = { + raw: this.input.slice(this.tok.start, this.tok.end).replace(/\r\n?/g, "\n"), + cooked: this.tok.value + }; + } + this.next(); + elem.tail = this.tok.type === tokTypes.backQuote; + return this.finishNode(elem, "TemplateElement") +}; + +lp.parseTemplate = function() { + var node = this.startNode(); + this.next(); + node.expressions = []; + var curElt = this.parseTemplateElement(); + node.quasis = [curElt]; + while (!curElt.tail) { + this.next(); + node.expressions.push(this.parseExpression()); + if (this.expect(tokTypes.braceR)) { + curElt = this.parseTemplateElement(); + } else { + curElt = this.startNode(); + curElt.value = {cooked: "", raw: ""}; + curElt.tail = true; + this.finishNode(curElt, "TemplateElement"); + } + node.quasis.push(curElt); + } + this.expect(tokTypes.backQuote); + return this.finishNode(node, "TemplateLiteral") +}; + +lp.parseObj = function() { + var node = this.startNode(); + node.properties = []; + this.pushCx(); + var indent = this.curIndent + 1, line = this.curLineStart; + this.eat(tokTypes.braceL); + if (this.curIndent + 1 < indent) { indent = this.curIndent; line = this.curLineStart; } + while (!this.closes(tokTypes.braceR, indent, line)) { + var prop = this.startNode(), isGenerator = (void 0), isAsync = (void 0), start = (void 0); + if (this.options.ecmaVersion >= 9 && this.eat(tokTypes.ellipsis)) { + prop.argument = this.parseMaybeAssign(); + node.properties.push(this.finishNode(prop, "SpreadElement")); + this.eat(tokTypes.comma); + continue + } + if (this.options.ecmaVersion >= 6) { + start = this.storeCurrentPos(); + prop.method = false; + prop.shorthand = false; + isGenerator = this.eat(tokTypes.star); + } + this.parsePropertyName(prop); + if (this.toks.isAsyncProp(prop)) { + isAsync = true; + isGenerator = this.options.ecmaVersion >= 9 && this.eat(tokTypes.star); + this.parsePropertyName(prop); + } else { + isAsync = false; + } + if (isDummy(prop.key)) { if (isDummy(this.parseMaybeAssign())) { this.next(); } this.eat(tokTypes.comma); continue } + if (this.eat(tokTypes.colon)) { + prop.kind = "init"; + prop.value = this.parseMaybeAssign(); + } else if (this.options.ecmaVersion >= 6 && (this.tok.type === tokTypes.parenL || this.tok.type === tokTypes.braceL)) { + prop.kind = "init"; + prop.method = true; + prop.value = this.parseMethod(isGenerator, isAsync); + } else if (this.options.ecmaVersion >= 5 && prop.key.type === "Identifier" && + !prop.computed && (prop.key.name === "get" || prop.key.name === "set") && + (this.tok.type !== tokTypes.comma && this.tok.type !== tokTypes.braceR && this.tok.type !== tokTypes.eq)) { + prop.kind = prop.key.name; + this.parsePropertyName(prop); + prop.value = this.parseMethod(false); + } else { + prop.kind = "init"; + if (this.options.ecmaVersion >= 6) { + if (this.eat(tokTypes.eq)) { + var assign = this.startNodeAt(start); + assign.operator = "="; + assign.left = prop.key; + assign.right = this.parseMaybeAssign(); + prop.value = this.finishNode(assign, "AssignmentExpression"); + } else { + prop.value = prop.key; + } + } else { + prop.value = this.dummyIdent(); + } + prop.shorthand = true; + } + node.properties.push(this.finishNode(prop, "Property")); + this.eat(tokTypes.comma); + } + this.popCx(); + if (!this.eat(tokTypes.braceR)) { + // If there is no closing brace, make the node span to the start + // of the next token (this is useful for Tern) + this.last.end = this.tok.start; + if (this.options.locations) { this.last.loc.end = this.tok.loc.start; } + } + return this.finishNode(node, "ObjectExpression") +}; + +lp.parsePropertyName = function(prop) { + if (this.options.ecmaVersion >= 6) { + if (this.eat(tokTypes.bracketL)) { + prop.computed = true; + prop.key = this.parseExpression(); + this.expect(tokTypes.bracketR); + return + } else { + prop.computed = false; + } + } + var key = (this.tok.type === tokTypes.num || this.tok.type === tokTypes.string) ? this.parseExprAtom() : this.parseIdent(); + prop.key = key || this.dummyIdent(); +}; + +lp.parsePropertyAccessor = function() { + if (this.tok.type === tokTypes.name || this.tok.type.keyword) { return this.parseIdent() } + if (this.tok.type === tokTypes.privateId) { return this.parsePrivateIdent() } +}; + +lp.parseIdent = function() { + var name = this.tok.type === tokTypes.name ? this.tok.value : this.tok.type.keyword; + if (!name) { return this.dummyIdent() } + if (this.tok.type.keyword) { this.toks.type = tokTypes.name; } + var node = this.startNode(); + this.next(); + node.name = name; + return this.finishNode(node, "Identifier") +}; + +lp.parsePrivateIdent = function() { + var node = this.startNode(); + node.name = this.tok.value; + this.next(); + return this.finishNode(node, "PrivateIdentifier") +}; + +lp.initFunction = function(node) { + node.id = null; + node.params = []; + if (this.options.ecmaVersion >= 6) { + node.generator = false; + node.expression = false; + } + if (this.options.ecmaVersion >= 8) + { node.async = false; } +}; + +// Convert existing expression atom to assignable pattern +// if possible. + +lp.toAssignable = function(node, binding) { + if (!node || node.type === "Identifier" || (node.type === "MemberExpression" && !binding)) ; else if (node.type === "ParenthesizedExpression") { + this.toAssignable(node.expression, binding); + } else if (this.options.ecmaVersion < 6) { + return this.dummyIdent() + } else if (node.type === "ObjectExpression") { + node.type = "ObjectPattern"; + for (var i = 0, list = node.properties; i < list.length; i += 1) + { + var prop = list[i]; + + this.toAssignable(prop, binding); + } + } else if (node.type === "ArrayExpression") { + node.type = "ArrayPattern"; + this.toAssignableList(node.elements, binding); + } else if (node.type === "Property") { + this.toAssignable(node.value, binding); + } else if (node.type === "SpreadElement") { + node.type = "RestElement"; + this.toAssignable(node.argument, binding); + } else if (node.type === "AssignmentExpression") { + node.type = "AssignmentPattern"; + delete node.operator; + } else { + return this.dummyIdent() + } + return node +}; + +lp.toAssignableList = function(exprList, binding) { + for (var i = 0, list = exprList; i < list.length; i += 1) + { + var expr = list[i]; + + this.toAssignable(expr, binding); + } + return exprList +}; + +lp.parseFunctionParams = function(params) { + params = this.parseExprList(tokTypes.parenR); + return this.toAssignableList(params, true) +}; + +lp.parseMethod = function(isGenerator, isAsync) { + var node = this.startNode(), oldInAsync = this.inAsync, oldInGenerator = this.inGenerator, oldInFunction = this.inFunction; + this.initFunction(node); + if (this.options.ecmaVersion >= 6) + { node.generator = !!isGenerator; } + if (this.options.ecmaVersion >= 8) + { node.async = !!isAsync; } + this.inAsync = node.async; + this.inGenerator = node.generator; + this.inFunction = true; + node.params = this.parseFunctionParams(); + node.body = this.parseBlock(); + this.toks.adaptDirectivePrologue(node.body.body); + this.inAsync = oldInAsync; + this.inGenerator = oldInGenerator; + this.inFunction = oldInFunction; + return this.finishNode(node, "FunctionExpression") +}; + +lp.parseArrowExpression = function(node, params, isAsync) { + var oldInAsync = this.inAsync, oldInGenerator = this.inGenerator, oldInFunction = this.inFunction; + this.initFunction(node); + if (this.options.ecmaVersion >= 8) + { node.async = !!isAsync; } + this.inAsync = node.async; + this.inGenerator = false; + this.inFunction = true; + node.params = this.toAssignableList(params, true); + node.expression = this.tok.type !== tokTypes.braceL; + if (node.expression) { + node.body = this.parseMaybeAssign(); + } else { + node.body = this.parseBlock(); + this.toks.adaptDirectivePrologue(node.body.body); + } + this.inAsync = oldInAsync; + this.inGenerator = oldInGenerator; + this.inFunction = oldInFunction; + return this.finishNode(node, "ArrowFunctionExpression") +}; + +lp.parseExprList = function(close, allowEmpty) { + this.pushCx(); + var indent = this.curIndent, line = this.curLineStart, elts = []; + this.next(); // Opening bracket + while (!this.closes(close, indent + 1, line)) { + if (this.eat(tokTypes.comma)) { + elts.push(allowEmpty ? null : this.dummyIdent()); + continue + } + var elt = this.parseMaybeAssign(); + if (isDummy(elt)) { + if (this.closes(close, indent, line)) { break } + this.next(); + } else { + elts.push(elt); + } + this.eat(tokTypes.comma); + } + this.popCx(); + if (!this.eat(close)) { + // If there is no closing brace, make the node span to the start + // of the next token (this is useful for Tern) + this.last.end = this.tok.start; + if (this.options.locations) { this.last.loc.end = this.tok.loc.start; } + } + return elts +}; + +lp.parseAwait = function() { + var node = this.startNode(); + this.next(); + node.argument = this.parseMaybeUnary(); + return this.finishNode(node, "AwaitExpression") +}; + +// Acorn: Loose parser +// +// This module provides an alternative parser that exposes that same +// interface as the main module's `parse` function, but will try to +// parse anything as JavaScript, repairing syntax error the best it +// can. There are circumstances in which it will raise an error and +// give up, but they are very rare. The resulting AST will be a mostly +// valid JavaScript AST (as per the [ESTree spec][estree], except +// that: +// +// - Return outside functions is allowed +// +// - Label consistency (no conflicts, break only to existing labels) +// is not enforced. +// +// - Bogus Identifier nodes with a name of `"✖"` are inserted whenever +// the parser got too confused to return anything meaningful. +// +// [estree]: https://github.com/estree/estree +// +// The expected use for this is to *first* try `acorn.parse`, and only +// if that fails switch to the loose parser. The loose parser might +// parse badly indented code incorrectly, so **don't** use it as your +// default parser. +// +// Quite a lot of acorn.js is duplicated here. The alternative was to +// add a *lot* of extra cruft to that file, making it less readable +// and slower. Copying and editing the code allowed me to make +// invasive changes and simplifications without creating a complicated +// tangle. + + +defaultOptions.tabSize = 4; + +function parse(input, options) { + return LooseParser.parse(input, options) +} + +export { LooseParser, isDummy, parse }; diff --git a/node_modules/acorn-loose/package.json b/node_modules/acorn-loose/package.json new file mode 100644 index 0000000..6bf5980 --- /dev/null +++ b/node_modules/acorn-loose/package.json @@ -0,0 +1,50 @@ +{ + "name": "acorn-loose", + "description": "Error-tolerant ECMAScript parser", + "homepage": "https://github.com/acornjs/acorn", + "main": "dist/acorn-loose.js", + "module": "dist/acorn-loose.mjs", + "types": "dist/acorn-loose.d.ts", + "exports": { + ".": [ + { + "import": "./dist/acorn-loose.mjs", + "require": "./dist/acorn-loose.js", + "default": "./dist/acorn-loose.js" + }, + "./dist/acorn-loose.js" + ], + "./package.json": "./package.json" + }, + "version": "8.5.2", + "engines": { + "node": ">=0.4.0" + }, + "dependencies": { + "acorn": "^8.15.0" + }, + "maintainers": [ + { + "name": "Marijn Haverbeke", + "email": "marijnh@gmail.com", + "web": "https://marijnhaverbeke.nl" + }, + { + "name": "Ingvar Stepanyan", + "email": "me@rreverser.com", + "web": "https://rreverser.com/" + }, + { + "name": "Adrian Heine", + "web": "http://adrianheine.de" + } + ], + "repository": { + "type": "git", + "url": "https://github.com/acornjs/acorn.git" + }, + "scripts": { + "prepare": "cd ..; npm run build:loose" + }, + "license": "MIT" +} diff --git a/node_modules/acorn-walk/CHANGELOG.md b/node_modules/acorn-walk/CHANGELOG.md new file mode 100644 index 0000000..de4168f --- /dev/null +++ b/node_modules/acorn-walk/CHANGELOG.md @@ -0,0 +1,209 @@ +## 8.3.5 (2026-02-19) + +### Bug fixes + +Emit a more informative error message when trying to walk a node type that has no walker function. + +Specify callbacks in types to receive `AnyNode` type, so that they can be narrowed more easily. + +Support import attributes. + +## 8.3.4 (2024-09-09) + +### Bug fixes + +Walk SwitchCase nodes as separate nodes. + +## 8.3.3 (2024-01-11) + +### Bug fixes + +Make acorn a dependency because acorn-walk uses the types from that package. + +## 8.3.2 (2024-01-11) + +### Bug fixes + +Add missing type for `findNodeBefore`. + +## 8.3.1 (2023-12-06) + +### Bug fixes + +Add `Function` and `Class` to the `AggregateType` type, so that they can be used in walkers without raising a type error. + +Visitor functions are now called in such a way that their `this` refers to the object they are part of. + +## 8.3.0 (2023-10-26) + +### New features + +Use a set of new, much more precise, TypeScript types. + +## 8.2.0 (2021-09-06) + +### New features + +Add support for walking ES2022 class static blocks. + +## 8.1.1 (2021-06-29) + +### Bug fixes + +Include `base` in the type declarations. + +## 8.1.0 (2021-04-24) + +### New features + +Support node types for class fields and private methods. + +## 8.0.2 (2021-01-25) + +### Bug fixes + +Adjust package.json to work with Node 12.16.0 and 13.0-13.6. + +## 8.0.0 (2021-01-05) + +### Bug fixes + +Fix a bug where `full` and `fullAncestor` would skip nodes with overridden types. + +## 8.0.0 (2020-08-12) + +### New features + +The package can now be loaded directly as an ECMAScript module in node 13+. + +## 7.2.0 (2020-06-17) + +### New features + +Support optional chaining and nullish coalescing. + +Support `import.meta`. + +Add support for `export * as ns from "source"`. + +## 7.1.1 (2020-02-13) + +### Bug fixes + +Clean up the type definitions to actually work well with the main parser. + +## 7.1.0 (2020-02-11) + +### New features + +Add a TypeScript definition file for the library. + +## 7.0.0 (2017-08-12) + +### New features + +Support walking `ImportExpression` nodes. + +## 6.2.0 (2017-07-04) + +### New features + +Add support for `Import` nodes. + +## 6.1.0 (2018-09-28) + +### New features + +The walker now walks `TemplateElement` nodes. + +## 6.0.1 (2018-09-14) + +### Bug fixes + +Fix bad "main" field in package.json. + +## 6.0.0 (2018-09-14) + +### Breaking changes + +This is now a separate package, `acorn-walk`, rather than part of the main `acorn` package. + +The `ScopeBody` and `ScopeExpression` meta-node-types are no longer supported. + +## 5.7.1 (2018-06-15) + +### Bug fixes + +Make sure the walker and bin files are rebuilt on release (the previous release didn't get the up-to-date versions). + +## 5.7.0 (2018-06-15) + +### Bug fixes + +Fix crash in walker when walking a binding-less catch node. + +## 5.6.2 (2018-06-05) + +### Bug fixes + +In the walker, go back to allowing the `baseVisitor` argument to be null to default to the default base everywhere. + +## 5.6.1 (2018-06-01) + +### Bug fixes + +Fix regression when passing `null` as fourth argument to `walk.recursive`. + +## 5.6.0 (2018-05-31) + +### Bug fixes + +Fix a bug in the walker that caused a crash when walking an object pattern spread. + +## 5.5.1 (2018-03-06) + +### Bug fixes + +Fix regression in walker causing property values in object patterns to be walked as expressions. + +## 5.5.0 (2018-02-27) + +### Bug fixes + +Support object spread in the AST walker. + +## 5.4.1 (2018-02-02) + +### Bug fixes + +5.4.0 somehow accidentally included an old version of walk.js. + +## 5.2.0 (2017-10-30) + +### Bug fixes + +The `full` and `fullAncestor` walkers no longer visit nodes multiple times. + +## 5.1.0 (2017-07-05) + +### New features + +New walker functions `full` and `fullAncestor`. + +## 3.2.0 (2016-06-07) + +### New features + +Make it possible to use `visit.ancestor` with a walk state. + +## 3.1.0 (2016-04-18) + +### New features + +The walker now allows defining handlers for `CatchClause` nodes. + +## 2.5.2 (2015-10-27) + +### Fixes + +Fix bug where the walker walked an exported `let` statement as an expression. diff --git a/node_modules/acorn-walk/LICENSE b/node_modules/acorn-walk/LICENSE new file mode 100644 index 0000000..d6be6db --- /dev/null +++ b/node_modules/acorn-walk/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (C) 2012-2020 by various contributors (see AUTHORS) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/node_modules/acorn-walk/README.md b/node_modules/acorn-walk/README.md new file mode 100644 index 0000000..eaec57f --- /dev/null +++ b/node_modules/acorn-walk/README.md @@ -0,0 +1,124 @@ +# Acorn AST walker + +An abstract syntax tree walker for the +[ESTree](https://github.com/estree/estree) format. + +## Community + +Acorn is open source software released under an +[MIT license](https://github.com/acornjs/acorn/blob/master/acorn-walk/LICENSE). + +You are welcome to +[report bugs](https://github.com/acornjs/acorn/issues) or create pull +requests on [github](https://github.com/acornjs/acorn). + +## Installation + +The easiest way to install acorn is from [`npm`](https://www.npmjs.com/): + +```sh +npm install acorn-walk +``` + +Alternately, you can download the source and build acorn yourself: + +```sh +git clone https://github.com/acornjs/acorn.git +cd acorn +npm install +``` + +## Interface + +An algorithm for recursing through a syntax tree is stored as an +object, with a property for each tree node type holding a function +that will recurse through such a node. There are several ways to run +such a walker. + +**simple**`(node, visitors, base, state)` does a 'simple' walk over a +tree. `node` should be the AST node to walk, and `visitors` an object +with properties whose names correspond to node types in the [ESTree +spec](https://github.com/estree/estree). The properties should contain +functions that will be called with the node object and, if applicable +the state at that point. The last two arguments are optional. `base` +is a walker algorithm, and `state` is a start state. The default +walker will simply visit all statements and expressions and not +produce a meaningful state. (An example of a use of state is to track +scope at each point in the tree.) + +```js +import * as acorn from "acorn" +import * as walk from "acorn-walk" + +walk.simple(acorn.parse("let x = 10"), { + Literal(node) { + console.log(`Found a literal: ${node.value}`) + } +}) +``` + +**ancestor**`(node, visitors, base, state)` does a 'simple' walk over +a tree, building up an array of ancestor nodes (including the current node) +and passing the array to the callbacks as a third parameter. + +```js +import * as acorn from "acorn" +import * as walk from "acorn-walk" + +walk.ancestor(acorn.parse("foo('hi')"), { + Literal(_node, _state, ancestors) { + console.log("This literal's ancestors are:", ancestors.map(n => n.type)) + } +}) +``` + +**recursive**`(node, state, functions, base)` does a 'recursive' +walk, where the walker functions are responsible for continuing the +walk on the child nodes of their target node. `state` is the start +state, and `functions` should contain an object that maps node types +to walker functions. Such functions are called with `(node, state, c)` +arguments, and can cause the walk to continue on a sub-node by calling +the `c` argument on it with `(node, state)` arguments. The optional +`base` argument provides the fallback walker functions for node types +that aren't handled in the `functions` object. If not given, the +default walkers will be used. + +**make**`(functions, base)` builds a new walker object by using the +walker functions in `functions` and filling in the missing ones by +taking defaults from `base`. + +**full**`(node, callback, base, state)` does a 'full' walk over a +tree, calling the callback with the arguments (node, state, type) for +each node + +**fullAncestor**`(node, callback, base, state)` does a 'full' walk +over a tree, building up an array of ancestor nodes (including the +current node) and passing the array to the callbacks as a third +parameter. + +```js +import * as acorn from "acorn" +import * as walk from "acorn-walk" + +walk.full(acorn.parse("1 + 1"), node => { + console.log(`There's a ${node.type} node at ${node.ch}`) +}) +``` + +**findNodeAt**`(node, start, end, test, base, state)` tries to locate +a node in a tree at the given start and/or end offsets, which +satisfies the predicate `test`. `start` and `end` can be either `null` +(as wildcard) or a number. `test` may be a string (indicating a node +type) or a function that takes `(nodeType, node)` arguments and +returns a boolean indicating whether this node is interesting. `base` +and `state` are optional, and can be used to specify a custom walker. +Nodes are tested from inner to outer, so if two nodes match the +boundaries, the inner one will be preferred. + +**findNodeAround**`(node, pos, test, base, state)` is a lot like +`findNodeAt`, but will match any node that exists 'around' (spanning) +the given position. + +**findNodeAfter**`(node, pos, test, base, state)` is similar to +`findNodeAround`, but will match all nodes *after* the given position +(testing outer nodes before inner nodes). diff --git a/node_modules/acorn-walk/dist/walk.d.mts b/node_modules/acorn-walk/dist/walk.d.mts new file mode 100644 index 0000000..199c8a0 --- /dev/null +++ b/node_modules/acorn-walk/dist/walk.d.mts @@ -0,0 +1,152 @@ +import * as acorn from "acorn" + +export type FullWalkerCallback = ( + node: acorn.AnyNode, + state: TState, + type: string +) => void + +export type FullAncestorWalkerCallback = ( + node: acorn.AnyNode, + state: TState, + ancestors: acorn.AnyNode[], + type: string +) => void + +type AggregateType = { + Expression: acorn.Expression, + Statement: acorn.Statement, + Function: acorn.Function, + Class: acorn.Class, + Pattern: acorn.Pattern, + ForInit: acorn.VariableDeclaration | acorn.Expression +} + +export type SimpleVisitors = { + [type in acorn.AnyNode["type"]]?: (node: Extract, state: TState) => void +} & { + [type in keyof AggregateType]?: (node: AggregateType[type], state: TState) => void +} + +export type AncestorVisitors = { + [type in acorn.AnyNode["type"]]?: ( node: Extract, state: TState, ancestors: acorn.AnyNode[] +) => void +} & { + [type in keyof AggregateType]?: (node: AggregateType[type], state: TState, ancestors: acorn.AnyNode[]) => void +} + +export type WalkerCallback = (node: acorn.AnyNode, state: TState) => void + +export type RecursiveVisitors = { + [type in acorn.AnyNode["type"]]?: ( node: Extract, state: TState, callback: WalkerCallback) => void +} & { + [type in keyof AggregateType]?: (node: AggregateType[type], state: TState, callback: WalkerCallback) => void +} + +export type FindPredicate = (type: string, node: acorn.AnyNode) => boolean + +export interface Found { + node: acorn.AnyNode, + state: TState +} + +/** + * does a 'simple' walk over a tree + * @param node the AST node to walk + * @param visitors an object with properties whose names correspond to node types in the {@link https://github.com/estree/estree | ESTree spec}. The properties should contain functions that will be called with the node object and, if applicable the state at that point. + * @param base a walker algorithm + * @param state a start state. The default walker will simply visit all statements and expressions and not produce a meaningful state. (An example of a use of state is to track scope at each point in the tree.) + */ +export function simple( + node: acorn.Node, + visitors: SimpleVisitors, + base?: RecursiveVisitors, + state?: TState +): void + +/** + * does a 'simple' walk over a tree, building up an array of ancestor nodes (including the current node) and passing the array to the callbacks as a third parameter. + */ +export function ancestor( + node: acorn.Node, + visitors: AncestorVisitors, + base?: RecursiveVisitors, + state?: TState + ): void + +/** + * does a 'recursive' walk, where the walker functions are responsible for continuing the walk on the child nodes of their target node. + * @param node + * @param state the start state + * @param functions contain an object that maps node types to walker functions + * @param base provides the fallback walker functions for node types that aren't handled in the {@link functions} object. If not given, the default walkers will be used. + */ +export function recursive( + node: acorn.Node, + state: TState, + functions: RecursiveVisitors, + base?: RecursiveVisitors +): void + +/** + * does a 'full' walk over a tree, calling the {@link callback} with the arguments (node, state, type) for each node + */ +export function full( + node: acorn.Node, + callback: FullWalkerCallback, + base?: RecursiveVisitors, + state?: TState +): void + +/** + * does a 'full' walk over a tree, building up an array of ancestor nodes (including the current node) and passing the array to the callbacks as a third parameter. + */ +export function fullAncestor( + node: acorn.Node, + callback: FullAncestorWalkerCallback, + base?: RecursiveVisitors, + state?: TState +): void + +/** + * builds a new walker object by using the walker functions in {@link functions} and filling in the missing ones by taking defaults from {@link base}. + */ +export function make( + functions: RecursiveVisitors, + base?: RecursiveVisitors +): RecursiveVisitors + +/** + * tries to locate a node in a tree at the given start and/or end offsets, which satisfies the predicate test. {@link start} and {@link end} can be either `null` (as wildcard) or a `number`. {@link test} may be a string (indicating a node type) or a function that takes (nodeType, node) arguments and returns a boolean indicating whether this node is interesting. {@link base} and {@link state} are optional, and can be used to specify a custom walker. Nodes are tested from inner to outer, so if two nodes match the boundaries, the inner one will be preferred. + */ +export function findNodeAt( + node: acorn.Node, + start: number | undefined | null, + end?: number | undefined | null, + type?: FindPredicate | string, + base?: RecursiveVisitors, + state?: TState +): Found | undefined + +/** + * like {@link findNodeAt}, but will match any node that exists 'around' (spanning) the given position. + */ +export function findNodeAround( + node: acorn.Node, + start: number | undefined | null, + type?: FindPredicate | string, + base?: RecursiveVisitors, + state?: TState +): Found | undefined + +/** + * Find the outermost matching node after a given position. + */ +export const findNodeAfter: typeof findNodeAround + +/** + * Find the outermost matching node before a given position. + */ +export const findNodeBefore: typeof findNodeAround + +export const base: RecursiveVisitors diff --git a/node_modules/acorn-walk/dist/walk.d.ts b/node_modules/acorn-walk/dist/walk.d.ts new file mode 100644 index 0000000..199c8a0 --- /dev/null +++ b/node_modules/acorn-walk/dist/walk.d.ts @@ -0,0 +1,152 @@ +import * as acorn from "acorn" + +export type FullWalkerCallback = ( + node: acorn.AnyNode, + state: TState, + type: string +) => void + +export type FullAncestorWalkerCallback = ( + node: acorn.AnyNode, + state: TState, + ancestors: acorn.AnyNode[], + type: string +) => void + +type AggregateType = { + Expression: acorn.Expression, + Statement: acorn.Statement, + Function: acorn.Function, + Class: acorn.Class, + Pattern: acorn.Pattern, + ForInit: acorn.VariableDeclaration | acorn.Expression +} + +export type SimpleVisitors = { + [type in acorn.AnyNode["type"]]?: (node: Extract, state: TState) => void +} & { + [type in keyof AggregateType]?: (node: AggregateType[type], state: TState) => void +} + +export type AncestorVisitors = { + [type in acorn.AnyNode["type"]]?: ( node: Extract, state: TState, ancestors: acorn.AnyNode[] +) => void +} & { + [type in keyof AggregateType]?: (node: AggregateType[type], state: TState, ancestors: acorn.AnyNode[]) => void +} + +export type WalkerCallback = (node: acorn.AnyNode, state: TState) => void + +export type RecursiveVisitors = { + [type in acorn.AnyNode["type"]]?: ( node: Extract, state: TState, callback: WalkerCallback) => void +} & { + [type in keyof AggregateType]?: (node: AggregateType[type], state: TState, callback: WalkerCallback) => void +} + +export type FindPredicate = (type: string, node: acorn.AnyNode) => boolean + +export interface Found { + node: acorn.AnyNode, + state: TState +} + +/** + * does a 'simple' walk over a tree + * @param node the AST node to walk + * @param visitors an object with properties whose names correspond to node types in the {@link https://github.com/estree/estree | ESTree spec}. The properties should contain functions that will be called with the node object and, if applicable the state at that point. + * @param base a walker algorithm + * @param state a start state. The default walker will simply visit all statements and expressions and not produce a meaningful state. (An example of a use of state is to track scope at each point in the tree.) + */ +export function simple( + node: acorn.Node, + visitors: SimpleVisitors, + base?: RecursiveVisitors, + state?: TState +): void + +/** + * does a 'simple' walk over a tree, building up an array of ancestor nodes (including the current node) and passing the array to the callbacks as a third parameter. + */ +export function ancestor( + node: acorn.Node, + visitors: AncestorVisitors, + base?: RecursiveVisitors, + state?: TState + ): void + +/** + * does a 'recursive' walk, where the walker functions are responsible for continuing the walk on the child nodes of their target node. + * @param node + * @param state the start state + * @param functions contain an object that maps node types to walker functions + * @param base provides the fallback walker functions for node types that aren't handled in the {@link functions} object. If not given, the default walkers will be used. + */ +export function recursive( + node: acorn.Node, + state: TState, + functions: RecursiveVisitors, + base?: RecursiveVisitors +): void + +/** + * does a 'full' walk over a tree, calling the {@link callback} with the arguments (node, state, type) for each node + */ +export function full( + node: acorn.Node, + callback: FullWalkerCallback, + base?: RecursiveVisitors, + state?: TState +): void + +/** + * does a 'full' walk over a tree, building up an array of ancestor nodes (including the current node) and passing the array to the callbacks as a third parameter. + */ +export function fullAncestor( + node: acorn.Node, + callback: FullAncestorWalkerCallback, + base?: RecursiveVisitors, + state?: TState +): void + +/** + * builds a new walker object by using the walker functions in {@link functions} and filling in the missing ones by taking defaults from {@link base}. + */ +export function make( + functions: RecursiveVisitors, + base?: RecursiveVisitors +): RecursiveVisitors + +/** + * tries to locate a node in a tree at the given start and/or end offsets, which satisfies the predicate test. {@link start} and {@link end} can be either `null` (as wildcard) or a `number`. {@link test} may be a string (indicating a node type) or a function that takes (nodeType, node) arguments and returns a boolean indicating whether this node is interesting. {@link base} and {@link state} are optional, and can be used to specify a custom walker. Nodes are tested from inner to outer, so if two nodes match the boundaries, the inner one will be preferred. + */ +export function findNodeAt( + node: acorn.Node, + start: number | undefined | null, + end?: number | undefined | null, + type?: FindPredicate | string, + base?: RecursiveVisitors, + state?: TState +): Found | undefined + +/** + * like {@link findNodeAt}, but will match any node that exists 'around' (spanning) the given position. + */ +export function findNodeAround( + node: acorn.Node, + start: number | undefined | null, + type?: FindPredicate | string, + base?: RecursiveVisitors, + state?: TState +): Found | undefined + +/** + * Find the outermost matching node after a given position. + */ +export const findNodeAfter: typeof findNodeAround + +/** + * Find the outermost matching node before a given position. + */ +export const findNodeBefore: typeof findNodeAround + +export const base: RecursiveVisitors diff --git a/node_modules/acorn-walk/dist/walk.js b/node_modules/acorn-walk/dist/walk.js new file mode 100644 index 0000000..fe4d197 --- /dev/null +++ b/node_modules/acorn-walk/dist/walk.js @@ -0,0 +1,485 @@ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : + typeof define === 'function' && define.amd ? define(['exports'], factory) : + (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory((global.acorn = global.acorn || {}, global.acorn.walk = {}))); +})(this, (function (exports) { 'use strict'; + + // AST walker module for ESTree compatible trees + + // A simple walk is one where you simply specify callbacks to be + // called on specific nodes. The last two arguments are optional. A + // simple use would be + // + // walk.simple(myTree, { + // Expression: function(node) { ... } + // }); + // + // to do something with all expressions. All ESTree node types + // can be used to identify node types, as well as Expression and + // Statement, which denote categories of nodes. + // + // The base argument can be used to pass a custom (recursive) + // walker, and state can be used to give this walked an initial + // state. + + function simple(node, visitors, baseVisitor, state, override) { + if (!baseVisitor) { baseVisitor = base + ; }(function c(node, st, override) { + var type = override || node.type; + visitNode(baseVisitor, type, node, st, c); + if (visitors[type]) { visitors[type](node, st); } + })(node, state, override); + } + + // An ancestor walk keeps an array of ancestor nodes (including the + // current node) and passes them to the callback as third parameter + // (and also as state parameter when no other state is present). + function ancestor(node, visitors, baseVisitor, state, override) { + var ancestors = []; + if (!baseVisitor) { baseVisitor = base + ; }(function c(node, st, override) { + var type = override || node.type; + var isNew = node !== ancestors[ancestors.length - 1]; + if (isNew) { ancestors.push(node); } + visitNode(baseVisitor, type, node, st, c); + if (visitors[type]) { visitors[type](node, st || ancestors, ancestors); } + if (isNew) { ancestors.pop(); } + })(node, state, override); + } + + // A recursive walk is one where your functions override the default + // walkers. They can modify and replace the state parameter that's + // threaded through the walk, and can opt how and whether to walk + // their child nodes (by calling their third argument on these + // nodes). + function recursive(node, state, funcs, baseVisitor, override) { + var visitor = funcs ? make(funcs, baseVisitor || undefined) : baseVisitor + ;(function c(node, st, override) { + visitor[override || node.type](node, st, c); + })(node, state, override); + } + + function makeTest(test) { + if (typeof test === "string") + { return function (type) { return type === test; } } + else if (!test) + { return function () { return true; } } + else + { return test } + } + + var Found = function Found(node, state) { this.node = node; this.state = state; }; + + // A full walk triggers the callback on each node + function full(node, callback, baseVisitor, state, override) { + if (!baseVisitor) { baseVisitor = base; } + var last + ;(function c(node, st, override) { + var type = override || node.type; + visitNode(baseVisitor, type, node, st, c); + if (last !== node) { + callback(node, st, type); + last = node; + } + })(node, state, override); + } + + // An fullAncestor walk is like an ancestor walk, but triggers + // the callback on each node + function fullAncestor(node, callback, baseVisitor, state) { + if (!baseVisitor) { baseVisitor = base; } + var ancestors = [], last + ;(function c(node, st, override) { + var type = override || node.type; + var isNew = node !== ancestors[ancestors.length - 1]; + if (isNew) { ancestors.push(node); } + visitNode(baseVisitor, type, node, st, c); + if (last !== node) { + callback(node, st || ancestors, ancestors, type); + last = node; + } + if (isNew) { ancestors.pop(); } + })(node, state); + } + + // Find a node with a given start, end, and type (all are optional, + // null can be used as wildcard). Returns a {node, state} object, or + // undefined when it doesn't find a matching node. + function findNodeAt(node, start, end, test, baseVisitor, state) { + if (!baseVisitor) { baseVisitor = base; } + test = makeTest(test); + try { + (function c(node, st, override) { + var type = override || node.type; + if ((start == null || node.start <= start) && + (end == null || node.end >= end)) + { visitNode(baseVisitor, type, node, st, c); } + if ((start == null || node.start === start) && + (end == null || node.end === end) && + test(type, node)) + { throw new Found(node, st) } + })(node, state); + } catch (e) { + if (e instanceof Found) { return e } + throw e + } + } + + // Find the innermost node of a given type that contains the given + // position. Interface similar to findNodeAt. + function findNodeAround(node, pos, test, baseVisitor, state) { + test = makeTest(test); + if (!baseVisitor) { baseVisitor = base; } + try { + (function c(node, st, override) { + var type = override || node.type; + if (node.start > pos || node.end < pos) { return } + visitNode(baseVisitor, type, node, st, c); + if (test(type, node)) { throw new Found(node, st) } + })(node, state); + } catch (e) { + if (e instanceof Found) { return e } + throw e + } + } + + // Find the outermost matching node after a given position. + function findNodeAfter(node, pos, test, baseVisitor, state) { + test = makeTest(test); + if (!baseVisitor) { baseVisitor = base; } + try { + (function c(node, st, override) { + if (node.end < pos) { return } + var type = override || node.type; + if (node.start >= pos && test(type, node)) { throw new Found(node, st) } + visitNode(baseVisitor, type, node, st, c); + })(node, state); + } catch (e) { + if (e instanceof Found) { return e } + throw e + } + } + + // Find the outermost matching node before a given position. + function findNodeBefore(node, pos, test, baseVisitor, state) { + test = makeTest(test); + if (!baseVisitor) { baseVisitor = base; } + var max + ;(function c(node, st, override) { + if (node.start > pos) { return } + var type = override || node.type; + if (node.end <= pos && (!max || max.node.end < node.end) && test(type, node)) + { max = new Found(node, st); } + visitNode(baseVisitor, type, node, st, c); + })(node, state); + return max + } + + // Used to create a custom walker. Will fill in all missing node + // type properties with the defaults. + function make(funcs, baseVisitor) { + var visitor = Object.create(baseVisitor || base); + for (var type in funcs) { visitor[type] = funcs[type]; } + return visitor + } + + function skipThrough(node, st, c) { c(node, st); } + function ignore(_node, _st, _c) {} + + function visitNode(baseVisitor, type, node, st, c) { + if (baseVisitor[type] == null) { throw new Error(("No walker function defined for node type " + type)) } + baseVisitor[type](node, st, c); + } + + // Node walkers. + + var base = {}; + + base.Program = base.BlockStatement = base.StaticBlock = function (node, st, c) { + for (var i = 0, list = node.body; i < list.length; i += 1) + { + var stmt = list[i]; + + c(stmt, st, "Statement"); + } + }; + base.Statement = skipThrough; + base.EmptyStatement = ignore; + base.ExpressionStatement = base.ParenthesizedExpression = base.ChainExpression = + function (node, st, c) { return c(node.expression, st, "Expression"); }; + base.IfStatement = function (node, st, c) { + c(node.test, st, "Expression"); + c(node.consequent, st, "Statement"); + if (node.alternate) { c(node.alternate, st, "Statement"); } + }; + base.LabeledStatement = function (node, st, c) { return c(node.body, st, "Statement"); }; + base.BreakStatement = base.ContinueStatement = ignore; + base.WithStatement = function (node, st, c) { + c(node.object, st, "Expression"); + c(node.body, st, "Statement"); + }; + base.SwitchStatement = function (node, st, c) { + c(node.discriminant, st, "Expression"); + for (var i = 0, list = node.cases; i < list.length; i += 1) { + var cs = list[i]; + + c(cs, st); + } + }; + base.SwitchCase = function (node, st, c) { + if (node.test) { c(node.test, st, "Expression"); } + for (var i = 0, list = node.consequent; i < list.length; i += 1) + { + var cons = list[i]; + + c(cons, st, "Statement"); + } + }; + base.ReturnStatement = base.YieldExpression = base.AwaitExpression = function (node, st, c) { + if (node.argument) { c(node.argument, st, "Expression"); } + }; + base.ThrowStatement = base.SpreadElement = + function (node, st, c) { return c(node.argument, st, "Expression"); }; + base.TryStatement = function (node, st, c) { + c(node.block, st, "Statement"); + if (node.handler) { c(node.handler, st); } + if (node.finalizer) { c(node.finalizer, st, "Statement"); } + }; + base.CatchClause = function (node, st, c) { + if (node.param) { c(node.param, st, "Pattern"); } + c(node.body, st, "Statement"); + }; + base.WhileStatement = base.DoWhileStatement = function (node, st, c) { + c(node.test, st, "Expression"); + c(node.body, st, "Statement"); + }; + base.ForStatement = function (node, st, c) { + if (node.init) { c(node.init, st, "ForInit"); } + if (node.test) { c(node.test, st, "Expression"); } + if (node.update) { c(node.update, st, "Expression"); } + c(node.body, st, "Statement"); + }; + base.ForInStatement = base.ForOfStatement = function (node, st, c) { + c(node.left, st, "ForInit"); + c(node.right, st, "Expression"); + c(node.body, st, "Statement"); + }; + base.ForInit = function (node, st, c) { + if (node.type === "VariableDeclaration") { c(node, st); } + else { c(node, st, "Expression"); } + }; + base.DebuggerStatement = ignore; + + base.FunctionDeclaration = function (node, st, c) { return c(node, st, "Function"); }; + base.VariableDeclaration = function (node, st, c) { + for (var i = 0, list = node.declarations; i < list.length; i += 1) + { + var decl = list[i]; + + c(decl, st); + } + }; + base.VariableDeclarator = function (node, st, c) { + c(node.id, st, "Pattern"); + if (node.init) { c(node.init, st, "Expression"); } + }; + + base.Function = function (node, st, c) { + if (node.id) { c(node.id, st, "Pattern"); } + for (var i = 0, list = node.params; i < list.length; i += 1) + { + var param = list[i]; + + c(param, st, "Pattern"); + } + c(node.body, st, node.expression ? "Expression" : "Statement"); + }; + + base.Pattern = function (node, st, c) { + if (node.type === "Identifier") + { c(node, st, "VariablePattern"); } + else if (node.type === "MemberExpression") + { c(node, st, "MemberPattern"); } + else + { c(node, st); } + }; + base.VariablePattern = ignore; + base.MemberPattern = skipThrough; + base.RestElement = function (node, st, c) { return c(node.argument, st, "Pattern"); }; + base.ArrayPattern = function (node, st, c) { + for (var i = 0, list = node.elements; i < list.length; i += 1) { + var elt = list[i]; + + if (elt) { c(elt, st, "Pattern"); } + } + }; + base.ObjectPattern = function (node, st, c) { + for (var i = 0, list = node.properties; i < list.length; i += 1) { + var prop = list[i]; + + if (prop.type === "Property") { + if (prop.computed) { c(prop.key, st, "Expression"); } + c(prop.value, st, "Pattern"); + } else if (prop.type === "RestElement") { + c(prop.argument, st, "Pattern"); + } + } + }; + + base.Expression = skipThrough; + base.ThisExpression = base.Super = base.MetaProperty = ignore; + base.ArrayExpression = function (node, st, c) { + for (var i = 0, list = node.elements; i < list.length; i += 1) { + var elt = list[i]; + + if (elt) { c(elt, st, "Expression"); } + } + }; + base.ObjectExpression = function (node, st, c) { + for (var i = 0, list = node.properties; i < list.length; i += 1) + { + var prop = list[i]; + + c(prop, st); + } + }; + base.FunctionExpression = base.ArrowFunctionExpression = base.FunctionDeclaration; + base.SequenceExpression = function (node, st, c) { + for (var i = 0, list = node.expressions; i < list.length; i += 1) + { + var expr = list[i]; + + c(expr, st, "Expression"); + } + }; + base.TemplateLiteral = function (node, st, c) { + for (var i = 0, list = node.quasis; i < list.length; i += 1) + { + var quasi = list[i]; + + c(quasi, st); + } + + for (var i$1 = 0, list$1 = node.expressions; i$1 < list$1.length; i$1 += 1) + { + var expr = list$1[i$1]; + + c(expr, st, "Expression"); + } + }; + base.TemplateElement = ignore; + base.UnaryExpression = base.UpdateExpression = function (node, st, c) { + c(node.argument, st, "Expression"); + }; + base.BinaryExpression = base.LogicalExpression = function (node, st, c) { + c(node.left, st, "Expression"); + c(node.right, st, "Expression"); + }; + base.AssignmentExpression = base.AssignmentPattern = function (node, st, c) { + c(node.left, st, "Pattern"); + c(node.right, st, "Expression"); + }; + base.ConditionalExpression = function (node, st, c) { + c(node.test, st, "Expression"); + c(node.consequent, st, "Expression"); + c(node.alternate, st, "Expression"); + }; + base.NewExpression = base.CallExpression = function (node, st, c) { + c(node.callee, st, "Expression"); + if (node.arguments) + { for (var i = 0, list = node.arguments; i < list.length; i += 1) + { + var arg = list[i]; + + c(arg, st, "Expression"); + } } + }; + base.MemberExpression = function (node, st, c) { + c(node.object, st, "Expression"); + if (node.computed) { c(node.property, st, "Expression"); } + }; + base.ExportNamedDeclaration = base.ExportDefaultDeclaration = function (node, st, c) { + if (node.declaration) + { c(node.declaration, st, node.type === "ExportNamedDeclaration" || node.declaration.id ? "Statement" : "Expression"); } + if (node.source) { c(node.source, st, "Expression"); } + if (node.attributes) + { for (var i = 0, list = node.attributes; i < list.length; i += 1) + { + var attr = list[i]; + + c(attr, st); + } } + }; + base.ExportAllDeclaration = function (node, st, c) { + if (node.exported) + { c(node.exported, st); } + c(node.source, st, "Expression"); + if (node.attributes) + { for (var i = 0, list = node.attributes; i < list.length; i += 1) + { + var attr = list[i]; + + c(attr, st); + } } + }; + base.ImportAttribute = function (node, st, c) { + c(node.value, st, "Expression"); + }; + base.ImportDeclaration = function (node, st, c) { + for (var i = 0, list = node.specifiers; i < list.length; i += 1) + { + var spec = list[i]; + + c(spec, st); + } + c(node.source, st, "Expression"); + if (node.attributes) + { for (var i$1 = 0, list$1 = node.attributes; i$1 < list$1.length; i$1 += 1) + { + var attr = list$1[i$1]; + + c(attr, st); + } } + }; + base.ImportExpression = function (node, st, c) { + c(node.source, st, "Expression"); + if (node.options) { c(node.options, st, "Expression"); } + }; + base.ImportSpecifier = base.ImportDefaultSpecifier = base.ImportNamespaceSpecifier = base.Identifier = base.PrivateIdentifier = base.Literal = ignore; + + base.TaggedTemplateExpression = function (node, st, c) { + c(node.tag, st, "Expression"); + c(node.quasi, st, "Expression"); + }; + base.ClassDeclaration = base.ClassExpression = function (node, st, c) { return c(node, st, "Class"); }; + base.Class = function (node, st, c) { + if (node.id) { c(node.id, st, "Pattern"); } + if (node.superClass) { c(node.superClass, st, "Expression"); } + c(node.body, st); + }; + base.ClassBody = function (node, st, c) { + for (var i = 0, list = node.body; i < list.length; i += 1) + { + var elt = list[i]; + + c(elt, st); + } + }; + base.MethodDefinition = base.PropertyDefinition = base.Property = function (node, st, c) { + if (node.computed) { c(node.key, st, "Expression"); } + if (node.value) { c(node.value, st, "Expression"); } + }; + + exports.ancestor = ancestor; + exports.base = base; + exports.findNodeAfter = findNodeAfter; + exports.findNodeAround = findNodeAround; + exports.findNodeAt = findNodeAt; + exports.findNodeBefore = findNodeBefore; + exports.full = full; + exports.fullAncestor = fullAncestor; + exports.make = make; + exports.recursive = recursive; + exports.simple = simple; + +})); diff --git a/node_modules/acorn-walk/dist/walk.mjs b/node_modules/acorn-walk/dist/walk.mjs new file mode 100644 index 0000000..88f18bb --- /dev/null +++ b/node_modules/acorn-walk/dist/walk.mjs @@ -0,0 +1,467 @@ +// AST walker module for ESTree compatible trees + +// A simple walk is one where you simply specify callbacks to be +// called on specific nodes. The last two arguments are optional. A +// simple use would be +// +// walk.simple(myTree, { +// Expression: function(node) { ... } +// }); +// +// to do something with all expressions. All ESTree node types +// can be used to identify node types, as well as Expression and +// Statement, which denote categories of nodes. +// +// The base argument can be used to pass a custom (recursive) +// walker, and state can be used to give this walked an initial +// state. + +function simple(node, visitors, baseVisitor, state, override) { + if (!baseVisitor) { baseVisitor = base + ; }(function c(node, st, override) { + var type = override || node.type; + visitNode(baseVisitor, type, node, st, c); + if (visitors[type]) { visitors[type](node, st); } + })(node, state, override); +} + +// An ancestor walk keeps an array of ancestor nodes (including the +// current node) and passes them to the callback as third parameter +// (and also as state parameter when no other state is present). +function ancestor(node, visitors, baseVisitor, state, override) { + var ancestors = []; + if (!baseVisitor) { baseVisitor = base + ; }(function c(node, st, override) { + var type = override || node.type; + var isNew = node !== ancestors[ancestors.length - 1]; + if (isNew) { ancestors.push(node); } + visitNode(baseVisitor, type, node, st, c); + if (visitors[type]) { visitors[type](node, st || ancestors, ancestors); } + if (isNew) { ancestors.pop(); } + })(node, state, override); +} + +// A recursive walk is one where your functions override the default +// walkers. They can modify and replace the state parameter that's +// threaded through the walk, and can opt how and whether to walk +// their child nodes (by calling their third argument on these +// nodes). +function recursive(node, state, funcs, baseVisitor, override) { + var visitor = funcs ? make(funcs, baseVisitor || undefined) : baseVisitor + ;(function c(node, st, override) { + visitor[override || node.type](node, st, c); + })(node, state, override); +} + +function makeTest(test) { + if (typeof test === "string") + { return function (type) { return type === test; } } + else if (!test) + { return function () { return true; } } + else + { return test } +} + +var Found = function Found(node, state) { this.node = node; this.state = state; }; + +// A full walk triggers the callback on each node +function full(node, callback, baseVisitor, state, override) { + if (!baseVisitor) { baseVisitor = base; } + var last + ;(function c(node, st, override) { + var type = override || node.type; + visitNode(baseVisitor, type, node, st, c); + if (last !== node) { + callback(node, st, type); + last = node; + } + })(node, state, override); +} + +// An fullAncestor walk is like an ancestor walk, but triggers +// the callback on each node +function fullAncestor(node, callback, baseVisitor, state) { + if (!baseVisitor) { baseVisitor = base; } + var ancestors = [], last + ;(function c(node, st, override) { + var type = override || node.type; + var isNew = node !== ancestors[ancestors.length - 1]; + if (isNew) { ancestors.push(node); } + visitNode(baseVisitor, type, node, st, c); + if (last !== node) { + callback(node, st || ancestors, ancestors, type); + last = node; + } + if (isNew) { ancestors.pop(); } + })(node, state); +} + +// Find a node with a given start, end, and type (all are optional, +// null can be used as wildcard). Returns a {node, state} object, or +// undefined when it doesn't find a matching node. +function findNodeAt(node, start, end, test, baseVisitor, state) { + if (!baseVisitor) { baseVisitor = base; } + test = makeTest(test); + try { + (function c(node, st, override) { + var type = override || node.type; + if ((start == null || node.start <= start) && + (end == null || node.end >= end)) + { visitNode(baseVisitor, type, node, st, c); } + if ((start == null || node.start === start) && + (end == null || node.end === end) && + test(type, node)) + { throw new Found(node, st) } + })(node, state); + } catch (e) { + if (e instanceof Found) { return e } + throw e + } +} + +// Find the innermost node of a given type that contains the given +// position. Interface similar to findNodeAt. +function findNodeAround(node, pos, test, baseVisitor, state) { + test = makeTest(test); + if (!baseVisitor) { baseVisitor = base; } + try { + (function c(node, st, override) { + var type = override || node.type; + if (node.start > pos || node.end < pos) { return } + visitNode(baseVisitor, type, node, st, c); + if (test(type, node)) { throw new Found(node, st) } + })(node, state); + } catch (e) { + if (e instanceof Found) { return e } + throw e + } +} + +// Find the outermost matching node after a given position. +function findNodeAfter(node, pos, test, baseVisitor, state) { + test = makeTest(test); + if (!baseVisitor) { baseVisitor = base; } + try { + (function c(node, st, override) { + if (node.end < pos) { return } + var type = override || node.type; + if (node.start >= pos && test(type, node)) { throw new Found(node, st) } + visitNode(baseVisitor, type, node, st, c); + })(node, state); + } catch (e) { + if (e instanceof Found) { return e } + throw e + } +} + +// Find the outermost matching node before a given position. +function findNodeBefore(node, pos, test, baseVisitor, state) { + test = makeTest(test); + if (!baseVisitor) { baseVisitor = base; } + var max + ;(function c(node, st, override) { + if (node.start > pos) { return } + var type = override || node.type; + if (node.end <= pos && (!max || max.node.end < node.end) && test(type, node)) + { max = new Found(node, st); } + visitNode(baseVisitor, type, node, st, c); + })(node, state); + return max +} + +// Used to create a custom walker. Will fill in all missing node +// type properties with the defaults. +function make(funcs, baseVisitor) { + var visitor = Object.create(baseVisitor || base); + for (var type in funcs) { visitor[type] = funcs[type]; } + return visitor +} + +function skipThrough(node, st, c) { c(node, st); } +function ignore(_node, _st, _c) {} + +function visitNode(baseVisitor, type, node, st, c) { + if (baseVisitor[type] == null) { throw new Error(("No walker function defined for node type " + type)) } + baseVisitor[type](node, st, c); +} + +// Node walkers. + +var base = {}; + +base.Program = base.BlockStatement = base.StaticBlock = function (node, st, c) { + for (var i = 0, list = node.body; i < list.length; i += 1) + { + var stmt = list[i]; + + c(stmt, st, "Statement"); + } +}; +base.Statement = skipThrough; +base.EmptyStatement = ignore; +base.ExpressionStatement = base.ParenthesizedExpression = base.ChainExpression = + function (node, st, c) { return c(node.expression, st, "Expression"); }; +base.IfStatement = function (node, st, c) { + c(node.test, st, "Expression"); + c(node.consequent, st, "Statement"); + if (node.alternate) { c(node.alternate, st, "Statement"); } +}; +base.LabeledStatement = function (node, st, c) { return c(node.body, st, "Statement"); }; +base.BreakStatement = base.ContinueStatement = ignore; +base.WithStatement = function (node, st, c) { + c(node.object, st, "Expression"); + c(node.body, st, "Statement"); +}; +base.SwitchStatement = function (node, st, c) { + c(node.discriminant, st, "Expression"); + for (var i = 0, list = node.cases; i < list.length; i += 1) { + var cs = list[i]; + + c(cs, st); + } +}; +base.SwitchCase = function (node, st, c) { + if (node.test) { c(node.test, st, "Expression"); } + for (var i = 0, list = node.consequent; i < list.length; i += 1) + { + var cons = list[i]; + + c(cons, st, "Statement"); + } +}; +base.ReturnStatement = base.YieldExpression = base.AwaitExpression = function (node, st, c) { + if (node.argument) { c(node.argument, st, "Expression"); } +}; +base.ThrowStatement = base.SpreadElement = + function (node, st, c) { return c(node.argument, st, "Expression"); }; +base.TryStatement = function (node, st, c) { + c(node.block, st, "Statement"); + if (node.handler) { c(node.handler, st); } + if (node.finalizer) { c(node.finalizer, st, "Statement"); } +}; +base.CatchClause = function (node, st, c) { + if (node.param) { c(node.param, st, "Pattern"); } + c(node.body, st, "Statement"); +}; +base.WhileStatement = base.DoWhileStatement = function (node, st, c) { + c(node.test, st, "Expression"); + c(node.body, st, "Statement"); +}; +base.ForStatement = function (node, st, c) { + if (node.init) { c(node.init, st, "ForInit"); } + if (node.test) { c(node.test, st, "Expression"); } + if (node.update) { c(node.update, st, "Expression"); } + c(node.body, st, "Statement"); +}; +base.ForInStatement = base.ForOfStatement = function (node, st, c) { + c(node.left, st, "ForInit"); + c(node.right, st, "Expression"); + c(node.body, st, "Statement"); +}; +base.ForInit = function (node, st, c) { + if (node.type === "VariableDeclaration") { c(node, st); } + else { c(node, st, "Expression"); } +}; +base.DebuggerStatement = ignore; + +base.FunctionDeclaration = function (node, st, c) { return c(node, st, "Function"); }; +base.VariableDeclaration = function (node, st, c) { + for (var i = 0, list = node.declarations; i < list.length; i += 1) + { + var decl = list[i]; + + c(decl, st); + } +}; +base.VariableDeclarator = function (node, st, c) { + c(node.id, st, "Pattern"); + if (node.init) { c(node.init, st, "Expression"); } +}; + +base.Function = function (node, st, c) { + if (node.id) { c(node.id, st, "Pattern"); } + for (var i = 0, list = node.params; i < list.length; i += 1) + { + var param = list[i]; + + c(param, st, "Pattern"); + } + c(node.body, st, node.expression ? "Expression" : "Statement"); +}; + +base.Pattern = function (node, st, c) { + if (node.type === "Identifier") + { c(node, st, "VariablePattern"); } + else if (node.type === "MemberExpression") + { c(node, st, "MemberPattern"); } + else + { c(node, st); } +}; +base.VariablePattern = ignore; +base.MemberPattern = skipThrough; +base.RestElement = function (node, st, c) { return c(node.argument, st, "Pattern"); }; +base.ArrayPattern = function (node, st, c) { + for (var i = 0, list = node.elements; i < list.length; i += 1) { + var elt = list[i]; + + if (elt) { c(elt, st, "Pattern"); } + } +}; +base.ObjectPattern = function (node, st, c) { + for (var i = 0, list = node.properties; i < list.length; i += 1) { + var prop = list[i]; + + if (prop.type === "Property") { + if (prop.computed) { c(prop.key, st, "Expression"); } + c(prop.value, st, "Pattern"); + } else if (prop.type === "RestElement") { + c(prop.argument, st, "Pattern"); + } + } +}; + +base.Expression = skipThrough; +base.ThisExpression = base.Super = base.MetaProperty = ignore; +base.ArrayExpression = function (node, st, c) { + for (var i = 0, list = node.elements; i < list.length; i += 1) { + var elt = list[i]; + + if (elt) { c(elt, st, "Expression"); } + } +}; +base.ObjectExpression = function (node, st, c) { + for (var i = 0, list = node.properties; i < list.length; i += 1) + { + var prop = list[i]; + + c(prop, st); + } +}; +base.FunctionExpression = base.ArrowFunctionExpression = base.FunctionDeclaration; +base.SequenceExpression = function (node, st, c) { + for (var i = 0, list = node.expressions; i < list.length; i += 1) + { + var expr = list[i]; + + c(expr, st, "Expression"); + } +}; +base.TemplateLiteral = function (node, st, c) { + for (var i = 0, list = node.quasis; i < list.length; i += 1) + { + var quasi = list[i]; + + c(quasi, st); + } + + for (var i$1 = 0, list$1 = node.expressions; i$1 < list$1.length; i$1 += 1) + { + var expr = list$1[i$1]; + + c(expr, st, "Expression"); + } +}; +base.TemplateElement = ignore; +base.UnaryExpression = base.UpdateExpression = function (node, st, c) { + c(node.argument, st, "Expression"); +}; +base.BinaryExpression = base.LogicalExpression = function (node, st, c) { + c(node.left, st, "Expression"); + c(node.right, st, "Expression"); +}; +base.AssignmentExpression = base.AssignmentPattern = function (node, st, c) { + c(node.left, st, "Pattern"); + c(node.right, st, "Expression"); +}; +base.ConditionalExpression = function (node, st, c) { + c(node.test, st, "Expression"); + c(node.consequent, st, "Expression"); + c(node.alternate, st, "Expression"); +}; +base.NewExpression = base.CallExpression = function (node, st, c) { + c(node.callee, st, "Expression"); + if (node.arguments) + { for (var i = 0, list = node.arguments; i < list.length; i += 1) + { + var arg = list[i]; + + c(arg, st, "Expression"); + } } +}; +base.MemberExpression = function (node, st, c) { + c(node.object, st, "Expression"); + if (node.computed) { c(node.property, st, "Expression"); } +}; +base.ExportNamedDeclaration = base.ExportDefaultDeclaration = function (node, st, c) { + if (node.declaration) + { c(node.declaration, st, node.type === "ExportNamedDeclaration" || node.declaration.id ? "Statement" : "Expression"); } + if (node.source) { c(node.source, st, "Expression"); } + if (node.attributes) + { for (var i = 0, list = node.attributes; i < list.length; i += 1) + { + var attr = list[i]; + + c(attr, st); + } } +}; +base.ExportAllDeclaration = function (node, st, c) { + if (node.exported) + { c(node.exported, st); } + c(node.source, st, "Expression"); + if (node.attributes) + { for (var i = 0, list = node.attributes; i < list.length; i += 1) + { + var attr = list[i]; + + c(attr, st); + } } +}; +base.ImportAttribute = function (node, st, c) { + c(node.value, st, "Expression"); +}; +base.ImportDeclaration = function (node, st, c) { + for (var i = 0, list = node.specifiers; i < list.length; i += 1) + { + var spec = list[i]; + + c(spec, st); + } + c(node.source, st, "Expression"); + if (node.attributes) + { for (var i$1 = 0, list$1 = node.attributes; i$1 < list$1.length; i$1 += 1) + { + var attr = list$1[i$1]; + + c(attr, st); + } } +}; +base.ImportExpression = function (node, st, c) { + c(node.source, st, "Expression"); + if (node.options) { c(node.options, st, "Expression"); } +}; +base.ImportSpecifier = base.ImportDefaultSpecifier = base.ImportNamespaceSpecifier = base.Identifier = base.PrivateIdentifier = base.Literal = ignore; + +base.TaggedTemplateExpression = function (node, st, c) { + c(node.tag, st, "Expression"); + c(node.quasi, st, "Expression"); +}; +base.ClassDeclaration = base.ClassExpression = function (node, st, c) { return c(node, st, "Class"); }; +base.Class = function (node, st, c) { + if (node.id) { c(node.id, st, "Pattern"); } + if (node.superClass) { c(node.superClass, st, "Expression"); } + c(node.body, st); +}; +base.ClassBody = function (node, st, c) { + for (var i = 0, list = node.body; i < list.length; i += 1) + { + var elt = list[i]; + + c(elt, st); + } +}; +base.MethodDefinition = base.PropertyDefinition = base.Property = function (node, st, c) { + if (node.computed) { c(node.key, st, "Expression"); } + if (node.value) { c(node.value, st, "Expression"); } +}; + +export { ancestor, base, findNodeAfter, findNodeAround, findNodeAt, findNodeBefore, full, fullAncestor, make, recursive, simple }; diff --git a/node_modules/acorn-walk/package.json b/node_modules/acorn-walk/package.json new file mode 100644 index 0000000..362add8 --- /dev/null +++ b/node_modules/acorn-walk/package.json @@ -0,0 +1,50 @@ +{ + "name": "acorn-walk", + "description": "ECMAScript (ESTree) AST walker", + "homepage": "https://github.com/acornjs/acorn", + "main": "dist/walk.js", + "types": "dist/walk.d.ts", + "module": "dist/walk.mjs", + "exports": { + ".": [ + { + "import": "./dist/walk.mjs", + "require": "./dist/walk.js", + "default": "./dist/walk.js" + }, + "./dist/walk.js" + ], + "./package.json": "./package.json" + }, + "version": "8.3.5", + "engines": { + "node": ">=0.4.0" + }, + "dependencies": { + "acorn": "^8.11.0" + }, + "maintainers": [ + { + "name": "Marijn Haverbeke", + "email": "marijnh@gmail.com", + "web": "https://marijnhaverbeke.nl" + }, + { + "name": "Ingvar Stepanyan", + "email": "me@rreverser.com", + "web": "https://rreverser.com/" + }, + { + "name": "Adrian Heine", + "web": "http://adrianheine.de" + } + ], + "repository": { + "type": "git", + "url": "https://github.com/acornjs/acorn.git" + }, + "scripts": { + "prepare": "cd ..; npm run build:walk" + }, + "license": "MIT" +} diff --git a/node_modules/acorn/CHANGELOG.md b/node_modules/acorn/CHANGELOG.md new file mode 100644 index 0000000..d18759a --- /dev/null +++ b/node_modules/acorn/CHANGELOG.md @@ -0,0 +1,972 @@ +## 8.16.0 (2026-02-19) + +### New features + +The `sourceType` option can now be set to `"commonjs"` to have the parser treat the top level scope as a function scope. + +Add support for Unicode 17. + +### Bug fixes + +Don't recognize `await using` as contextual keywords when followed directly by a backslash. + +Fix an issue where the parser would allow `return` statements in `static` blocks when `allowReturnOutsideFunction` was enabled. + +Properly reject `using` declarations that appear directly in `switch` or `for` head scopes. + +Fix some corner case issues in the recognition of `using` syntax. + +## 8.15.0 (2025-06-08) + +### New features + +Support `using` and `await using` syntax. + +The `AnyNode` type is now defined in such a way that plugins can extend it. + +### Bug fixes + +Fix an issue where the `bigint` property of literal nodes for non-decimal bigints had the wrong format. + +The `acorn` CLI tool no longer crashes when emitting a tree that contains a bigint. + +## 8.14.1 (2025-03-05) + +### Bug fixes + +Fix an issue where `await` expressions in class field initializers were inappropriately allowed. + +Properly allow await inside an async arrow function inside a class field initializer. + +Mention the source file name in syntax error messages when given. + +Properly add an empty `attributes` property to every form of `ExportNamedDeclaration`. + +## 8.14.0 (2024-10-27) + +### New features + +Support ES2025 import attributes. + +Support ES2025 RegExp modifiers. + +### Bug fixes + +Support some missing Unicode properties. + +## 8.13.0 (2024-10-16) + +### New features + +Upgrade to Unicode 16.0. + +## 8.12.1 (2024-07-03) + +### Bug fixes + +Fix a regression that caused Acorn to no longer run on Node versions <8.10. + +## 8.12.0 (2024-06-14) + +### New features + +Support ES2025 duplicate capture group names in regular expressions. + +### Bug fixes + +Include `VariableDeclarator` in the `AnyNode` type so that walker objects can refer to it without getting a type error. + +Properly raise a parse error for invalid `for`/`of` statements using `async` as binding name. + +Properly recognize \"use strict\" when preceded by a string with an escaped newline. + +Mark the `Parser` constructor as protected, not private, so plugins can extend it without type errors. + +Fix a bug where some invalid `delete` expressions were let through when the operand was parenthesized and `preserveParens` was enabled. + +Properly normalize line endings in raw strings of invalid template tokens. + +Properly track line numbers for escaped newlines in strings. + +Fix a bug that broke line number accounting after a template literal with invalid escape sequences. + +## 8.11.3 (2023-12-29) + +### Bug fixes + +Add `Function` and `Class` to the `AggregateType` type, so that they can be used in walkers without raising a type error. + +Make sure `onToken` get an `import` keyword token when parsing `import.meta`. + +Fix a bug where `.loc.start` could be undefined for `new.target` `meta` nodes. + +## 8.11.2 (2023-10-27) + +### Bug fixes + +Fix a bug that caused regular expressions after colon tokens to not be properly tokenized in some circumstances. + +## 8.11.1 (2023-10-26) + +### Bug fixes + +Fix a regression where `onToken` would receive 'name' tokens for 'new' keyword tokens. + +## 8.11.0 (2023-10-26) + +### Bug fixes + +Fix an issue where tokenizing (without parsing) an object literal with a property named `class` or `function` could, in some circumstance, put the tokenizer into an invalid state. + +Fix an issue where a slash after a call to a propery named the same as some keywords would be tokenized as a regular expression. + +### New features + +Upgrade to Unicode 15.1. + +Use a set of new, much more precise, TypeScript types. + +## 8.10.0 (2023-07-05) + +### New features + +Add a `checkPrivateFields` option that disables strict checking of private property use. + +## 8.9.0 (2023-06-16) + +### Bug fixes + +Forbid dynamic import after `new`, even when part of a member expression. + +### New features + +Add Unicode properties for ES2023. + +Add support for the `v` flag to regular expressions. + +## 8.8.2 (2023-01-23) + +### Bug fixes + +Fix a bug that caused `allowHashBang` to be set to false when not provided, even with `ecmaVersion >= 14`. + +Fix an exception when passing no option object to `parse` or `new Parser`. + +Fix incorrect parse error on `if (0) let\n[astral identifier char]`. + +## 8.8.1 (2022-10-24) + +### Bug fixes + +Make type for `Comment` compatible with estree types. + +## 8.8.0 (2022-07-21) + +### Bug fixes + +Allow parentheses around spread args in destructuring object assignment. + +Fix an issue where the tree contained `directive` properties in when parsing with a language version that doesn't support them. + +### New features + +Support hashbang comments by default in ECMAScript 2023 and later. + +## 8.7.1 (2021-04-26) + +### Bug fixes + +Stop handling `"use strict"` directives in ECMAScript versions before 5. + +Fix an issue where duplicate quoted export names in `export *` syntax were incorrectly checked. + +Add missing type for `tokTypes`. + +## 8.7.0 (2021-12-27) + +### New features + +Support quoted export names. + +Upgrade to Unicode 14. + +Add support for Unicode 13 properties in regular expressions. + +### Bug fixes + +Use a loop to find line breaks, because the existing regexp search would overrun the end of the searched range and waste a lot of time in minified code. + +## 8.6.0 (2021-11-18) + +### Bug fixes + +Fix a bug where an object literal with multiple `__proto__` properties would incorrectly be accepted if a later property value held an assigment. + +### New features + +Support class private fields with the `in` operator. + +## 8.5.0 (2021-09-06) + +### Bug fixes + +Improve context-dependent tokenization in a number of corner cases. + +Fix location tracking after a 0x2028 or 0x2029 character in a string literal (which before did not increase the line number). + +Fix an issue where arrow function bodies in for loop context would inappropriately consume `in` operators. + +Fix wrong end locations stored on SequenceExpression nodes. + +Implement restriction that `for`/`of` loop LHS can't start with `let`. + +### New features + +Add support for ES2022 class static blocks. + +Allow multiple input files to be passed to the CLI tool. + +## 8.4.1 (2021-06-24) + +### Bug fixes + +Fix a bug where `allowAwaitOutsideFunction` would allow `await` in class field initializers, and setting `ecmaVersion` to 13 or higher would allow top-level await in non-module sources. + +## 8.4.0 (2021-06-11) + +### New features + +A new option, `allowSuperOutsideMethod`, can be used to suppress the error when `super` is used in the wrong context. + +## 8.3.0 (2021-05-31) + +### New features + +Default `allowAwaitOutsideFunction` to true for ECMAScript 2022 an higher. + +Add support for the `d` ([indices](https://github.com/tc39/proposal-regexp-match-indices)) regexp flag. + +## 8.2.4 (2021-05-04) + +### Bug fixes + +Fix spec conformity in corner case 'for await (async of ...)'. + +## 8.2.3 (2021-05-04) + +### Bug fixes + +Fix an issue where the library couldn't parse 'for (async of ...)'. + +Fix a bug in UTF-16 decoding that would read characters incorrectly in some circumstances. + +## 8.2.2 (2021-04-29) + +### Bug fixes + +Fix a bug where a class field initialized to an async arrow function wouldn't allow await inside it. Same issue existed for generator arrow functions with yield. + +## 8.2.1 (2021-04-24) + +### Bug fixes + +Fix a regression introduced in 8.2.0 where static or async class methods with keyword names fail to parse. + +## 8.2.0 (2021-04-24) + +### New features + +Add support for ES2022 class fields and private methods. + +## 8.1.1 (2021-04-12) + +### Various + +Stop shipping source maps in the NPM package. + +## 8.1.0 (2021-03-09) + +### Bug fixes + +Fix a spurious error in nested destructuring arrays. + +### New features + +Expose `allowAwaitOutsideFunction` in CLI interface. + +Make `allowImportExportAnywhere` also apply to `import.meta`. + +## 8.0.5 (2021-01-25) + +### Bug fixes + +Adjust package.json to work with Node 12.16.0 and 13.0-13.6. + +## 8.0.4 (2020-10-05) + +### Bug fixes + +Make `await x ** y` an error, following the spec. + +Fix potentially exponential regular expression. + +## 8.0.3 (2020-10-02) + +### Bug fixes + +Fix a wasteful loop during `Parser` creation when setting `ecmaVersion` to `"latest"`. + +## 8.0.2 (2020-09-30) + +### Bug fixes + +Make the TypeScript types reflect the current allowed values for `ecmaVersion`. + +Fix another regexp/division tokenizer issue. + +## 8.0.1 (2020-08-12) + +### Bug fixes + +Provide the correct value in the `version` export. + +## 8.0.0 (2020-08-12) + +### Bug fixes + +Disallow expressions like `(a = b) = c`. + +Make non-octal escape sequences a syntax error in strict mode. + +### New features + +The package can now be loaded directly as an ECMAScript module in node 13+. + +Update to the set of Unicode properties from ES2021. + +### Breaking changes + +The `ecmaVersion` option is now required. For the moment, omitting it will still work with a warning, but that will change in a future release. + +Some changes to method signatures that may be used by plugins. + +## 7.4.0 (2020-08-03) + +### New features + +Add support for logical assignment operators. + +Add support for numeric separators. + +## 7.3.1 (2020-06-11) + +### Bug fixes + +Make the string in the `version` export match the actual library version. + +## 7.3.0 (2020-06-11) + +### Bug fixes + +Fix a bug that caused parsing of object patterns with a property named `set` that had a default value to fail. + +### New features + +Add support for optional chaining (`?.`). + +## 7.2.0 (2020-05-09) + +### Bug fixes + +Fix precedence issue in parsing of async arrow functions. + +### New features + +Add support for nullish coalescing. + +Add support for `import.meta`. + +Support `export * as ...` syntax. + +Upgrade to Unicode 13. + +## 6.4.1 (2020-03-09) + +### Bug fixes + +More carefully check for valid UTF16 surrogate pairs in regexp validator. + +## 7.1.1 (2020-03-01) + +### Bug fixes + +Treat `\8` and `\9` as invalid escapes in template strings. + +Allow unicode escapes in property names that are keywords. + +Don't error on an exponential operator expression as argument to `await`. + +More carefully check for valid UTF16 surrogate pairs in regexp validator. + +## 7.1.0 (2019-09-24) + +### Bug fixes + +Disallow trailing object literal commas when ecmaVersion is less than 5. + +### New features + +Add a static `acorn` property to the `Parser` class that contains the entire module interface, to allow plugins to access the instance of the library that they are acting on. + +## 7.0.0 (2019-08-13) + +### Breaking changes + +Changes the node format for dynamic imports to use the `ImportExpression` node type, as defined in [ESTree](https://github.com/estree/estree/blob/master/es2020.md#importexpression). + +Makes 10 (ES2019) the default value for the `ecmaVersion` option. + +## 6.3.0 (2019-08-12) + +### New features + +`sourceType: "module"` can now be used even when `ecmaVersion` is less than 6, to parse module-style code that otherwise conforms to an older standard. + +## 6.2.1 (2019-07-21) + +### Bug fixes + +Fix bug causing Acorn to treat some characters as identifier characters that shouldn't be treated as such. + +Fix issue where setting the `allowReserved` option to `"never"` allowed reserved words in some circumstances. + +## 6.2.0 (2019-07-04) + +### Bug fixes + +Improve valid assignment checking in `for`/`in` and `for`/`of` loops. + +Disallow binding `let` in patterns. + +### New features + +Support bigint syntax with `ecmaVersion` >= 11. + +Support dynamic `import` syntax with `ecmaVersion` >= 11. + +Upgrade to Unicode version 12. + +## 6.1.1 (2019-02-27) + +### Bug fixes + +Fix bug that caused parsing default exports of with names to fail. + +## 6.1.0 (2019-02-08) + +### Bug fixes + +Fix scope checking when redefining a `var` as a lexical binding. + +### New features + +Split up `parseSubscripts` to use an internal `parseSubscript` method to make it easier to extend with plugins. + +## 6.0.7 (2019-02-04) + +### Bug fixes + +Check that exported bindings are defined. + +Don't treat `\u180e` as a whitespace character. + +Check for duplicate parameter names in methods. + +Don't allow shorthand properties when they are generators or async methods. + +Forbid binding `await` in async arrow function's parameter list. + +## 6.0.6 (2019-01-30) + +### Bug fixes + +The content of class declarations and expressions is now always parsed in strict mode. + +Don't allow `let` or `const` to bind the variable name `let`. + +Treat class declarations as lexical. + +Don't allow a generator function declaration as the sole body of an `if` or `else`. + +Ignore `"use strict"` when after an empty statement. + +Allow string line continuations with special line terminator characters. + +Treat `for` bodies as part of the `for` scope when checking for conflicting bindings. + +Fix bug with parsing `yield` in a `for` loop initializer. + +Implement special cases around scope checking for functions. + +## 6.0.5 (2019-01-02) + +### Bug fixes + +Fix TypeScript type for `Parser.extend` and add `allowAwaitOutsideFunction` to options type. + +Don't treat `let` as a keyword when the next token is `{` on the next line. + +Fix bug that broke checking for parentheses around an object pattern in a destructuring assignment when `preserveParens` was on. + +## 6.0.4 (2018-11-05) + +### Bug fixes + +Further improvements to tokenizing regular expressions in corner cases. + +## 6.0.3 (2018-11-04) + +### Bug fixes + +Fix bug in tokenizing an expression-less return followed by a function followed by a regular expression. + +Remove stray symlink in the package tarball. + +## 6.0.2 (2018-09-26) + +### Bug fixes + +Fix bug where default expressions could fail to parse inside an object destructuring assignment expression. + +## 6.0.1 (2018-09-14) + +### Bug fixes + +Fix wrong value in `version` export. + +## 6.0.0 (2018-09-14) + +### Bug fixes + +Better handle variable-redefinition checks for catch bindings and functions directly under if statements. + +Forbid `new.target` in top-level arrow functions. + +Fix issue with parsing a regexp after `yield` in some contexts. + +### New features + +The package now comes with TypeScript definitions. + +### Breaking changes + +The default value of the `ecmaVersion` option is now 9 (2018). + +Plugins work differently, and will have to be rewritten to work with this version. + +The loose parser and walker have been moved into separate packages (`acorn-loose` and `acorn-walk`). + +## 5.7.3 (2018-09-10) + +### Bug fixes + +Fix failure to tokenize regexps after expressions like `x.of`. + +Better error message for unterminated template literals. + +## 5.7.2 (2018-08-24) + +### Bug fixes + +Properly handle `allowAwaitOutsideFunction` in for statements. + +Treat function declarations at the top level of modules like let bindings. + +Don't allow async function declarations as the only statement under a label. + +## 5.7.0 (2018-06-15) + +### New features + +Upgraded to Unicode 11. + +## 5.6.0 (2018-05-31) + +### New features + +Allow U+2028 and U+2029 in string when ECMAVersion >= 10. + +Allow binding-less catch statements when ECMAVersion >= 10. + +Add `allowAwaitOutsideFunction` option for parsing top-level `await`. + +## 5.5.3 (2018-03-08) + +### Bug fixes + +A _second_ republish of the code in 5.5.1, this time with yarn, to hopefully get valid timestamps. + +## 5.5.2 (2018-03-08) + +### Bug fixes + +A republish of the code in 5.5.1 in an attempt to solve an issue with the file timestamps in the npm package being 0. + +## 5.5.1 (2018-03-06) + +### Bug fixes + +Fix misleading error message for octal escapes in template strings. + +## 5.5.0 (2018-02-27) + +### New features + +The identifier character categorization is now based on Unicode version 10. + +Acorn will now validate the content of regular expressions, including new ES9 features. + +## 5.4.0 (2018-02-01) + +### Bug fixes + +Disallow duplicate or escaped flags on regular expressions. + +Disallow octal escapes in strings in strict mode. + +### New features + +Add support for async iteration. + +Add support for object spread and rest. + +## 5.3.0 (2017-12-28) + +### Bug fixes + +Fix parsing of floating point literals with leading zeroes in loose mode. + +Allow duplicate property names in object patterns. + +Don't allow static class methods named `prototype`. + +Disallow async functions directly under `if` or `else`. + +Parse right-hand-side of `for`/`of` as an assignment expression. + +Stricter parsing of `for`/`in`. + +Don't allow unicode escapes in contextual keywords. + +### New features + +Parsing class members was factored into smaller methods to allow plugins to hook into it. + +## 5.2.1 (2017-10-30) + +### Bug fixes + +Fix a token context corruption bug. + +## 5.2.0 (2017-10-30) + +### Bug fixes + +Fix token context tracking for `class` and `function` in property-name position. + +Make sure `%*` isn't parsed as a valid operator. + +Allow shorthand properties `get` and `set` to be followed by default values. + +Disallow `super` when not in callee or object position. + +### New features + +Support [`directive` property](https://github.com/estree/estree/compare/b3de58c9997504d6fba04b72f76e6dd1619ee4eb...1da8e603237144f44710360f8feb7a9977e905e0) on directive expression statements. + +## 5.1.2 (2017-09-04) + +### Bug fixes + +Disable parsing of legacy HTML-style comments in modules. + +Fix parsing of async methods whose names are keywords. + +## 5.1.1 (2017-07-06) + +### Bug fixes + +Fix problem with disambiguating regexp and division after a class. + +## 5.1.0 (2017-07-05) + +### Bug fixes + +Fix tokenizing of regexps in an object-desctructuring `for`/`of` loop and after `yield`. + +Parse zero-prefixed numbers with non-octal digits as decimal. + +Allow object/array patterns in rest parameters. + +Don't error when `yield` is used as a property name. + +Allow `async` as a shorthand object property. + +### New features + +Implement the [template literal revision proposal](https://github.com/tc39/proposal-template-literal-revision) for ES9. + +## 5.0.3 (2017-04-01) + +### Bug fixes + +Fix spurious duplicate variable definition errors for named functions. + +## 5.0.2 (2017-03-30) + +### Bug fixes + +A binary operator after a parenthesized arrow expression is no longer incorrectly treated as an error. + +## 5.0.0 (2017-03-28) + +### Bug fixes + +Raise an error for duplicated lexical bindings. + +Fix spurious error when an assignement expression occurred after a spread expression. + +Accept regular expressions after `of` (in `for`/`of`), `yield` (in a generator), and braced arrow functions. + +Allow labels in front or `var` declarations, even in strict mode. + +### Breaking changes + +Parse declarations following `export default` as declaration nodes, not expressions. This means that class and function declarations nodes can now have `null` as their `id`. + +## 4.0.11 (2017-02-07) + +### Bug fixes + +Allow all forms of member expressions to be parenthesized as lvalue. + +## 4.0.10 (2017-02-07) + +### Bug fixes + +Don't expect semicolons after default-exported functions or classes, even when they are expressions. + +Check for use of `'use strict'` directives in non-simple parameter functions, even when already in strict mode. + +## 4.0.9 (2017-02-06) + +### Bug fixes + +Fix incorrect error raised for parenthesized simple assignment targets, so that `(x) = 1` parses again. + +## 4.0.8 (2017-02-03) + +### Bug fixes + +Solve spurious parenthesized pattern errors by temporarily erring on the side of accepting programs that our delayed errors don't handle correctly yet. + +## 4.0.7 (2017-02-02) + +### Bug fixes + +Accept invalidly rejected code like `(x).y = 2` again. + +Don't raise an error when a function _inside_ strict code has a non-simple parameter list. + +## 4.0.6 (2017-02-02) + +### Bug fixes + +Fix exponential behavior (manifesting itself as a complete hang for even relatively small source files) introduced by the new 'use strict' check. + +## 4.0.5 (2017-02-02) + +### Bug fixes + +Disallow parenthesized pattern expressions. + +Allow keywords as export names. + +Don't allow the `async` keyword to be parenthesized. + +Properly raise an error when a keyword contains a character escape. + +Allow `"use strict"` to appear after other string literal expressions. + +Disallow labeled declarations. + +## 4.0.4 (2016-12-19) + +### Bug fixes + +Fix crash when `export` was followed by a keyword that can't be +exported. + +## 4.0.3 (2016-08-16) + +### Bug fixes + +Allow regular function declarations inside single-statement `if` branches in loose mode. Forbid them entirely in strict mode. + +Properly parse properties named `async` in ES2017 mode. + +Fix bug where reserved words were broken in ES2017 mode. + +## 4.0.2 (2016-08-11) + +### Bug fixes + +Don't ignore period or 'e' characters after octal numbers. + +Fix broken parsing for call expressions in default parameter values of arrow functions. + +## 4.0.1 (2016-08-08) + +### Bug fixes + +Fix false positives in duplicated export name errors. + +## 4.0.0 (2016-08-07) + +### Breaking changes + +The default `ecmaVersion` option value is now 7. + +A number of internal method signatures changed, so plugins might need to be updated. + +### Bug fixes + +The parser now raises errors on duplicated export names. + +`arguments` and `eval` can now be used in shorthand properties. + +Duplicate parameter names in non-simple argument lists now always produce an error. + +### New features + +The `ecmaVersion` option now also accepts year-style version numbers +(2015, etc). + +Support for `async`/`await` syntax when `ecmaVersion` is >= 8. + +Support for trailing commas in call expressions when `ecmaVersion` is >= 8. + +## 3.3.0 (2016-07-25) + +### Bug fixes + +Fix bug in tokenizing of regexp operator after a function declaration. + +Fix parser crash when parsing an array pattern with a hole. + +### New features + +Implement check against complex argument lists in functions that enable strict mode in ES7. + +## 3.2.0 (2016-06-07) + +### Bug fixes + +Improve handling of lack of unicode regexp support in host +environment. + +Properly reject shorthand properties whose name is a keyword. + +### New features + +Visitors created with `visit.make` now have their base as _prototype_, rather than copying properties into a fresh object. + +## 3.1.0 (2016-04-18) + +### Bug fixes + +Properly tokenize the division operator directly after a function expression. + +Allow trailing comma in destructuring arrays. + +## 3.0.4 (2016-02-25) + +### Fixes + +Allow update expressions as left-hand-side of the ES7 exponential operator. + +## 3.0.2 (2016-02-10) + +### Fixes + +Fix bug that accidentally made `undefined` a reserved word when parsing ES7. + +## 3.0.0 (2016-02-10) + +### Breaking changes + +The default value of the `ecmaVersion` option is now 6 (used to be 5). + +Support for comprehension syntax (which was dropped from the draft spec) has been removed. + +### Fixes + +`let` and `yield` are now “contextual keywords”, meaning you can mostly use them as identifiers in ES5 non-strict code. + +A parenthesized class or function expression after `export default` is now parsed correctly. + +### New features + +When `ecmaVersion` is set to 7, Acorn will parse the exponentiation operator (`**`). + +The identifier character ranges are now based on Unicode 8.0.0. + +Plugins can now override the `raiseRecoverable` method to override the way non-critical errors are handled. + +## 2.7.0 (2016-01-04) + +### Fixes + +Stop allowing rest parameters in setters. + +Disallow `y` rexexp flag in ES5. + +Disallow `\00` and `\000` escapes in strict mode. + +Raise an error when an import name is a reserved word. + +## 2.6.2 (2015-11-10) + +### Fixes + +Don't crash when no options object is passed. + +## 2.6.0 (2015-11-09) + +### Fixes + +Add `await` as a reserved word in module sources. + +Disallow `yield` in a parameter default value for a generator. + +Forbid using a comma after a rest pattern in an array destructuring. + +### New features + +Support parsing stdin in command-line tool. + +## 2.5.0 (2015-10-27) + +### Fixes + +Fix tokenizer support in the command-line tool. + +Stop allowing `new.target` outside of functions. + +Remove legacy `guard` and `guardedHandler` properties from try nodes. + +Stop allowing multiple `__proto__` properties on an object literal in strict mode. + +Don't allow rest parameters to be non-identifier patterns. + +Check for duplicate paramter names in arrow functions. diff --git a/node_modules/acorn/LICENSE b/node_modules/acorn/LICENSE new file mode 100644 index 0000000..9d71cc6 --- /dev/null +++ b/node_modules/acorn/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (C) 2012-2022 by various contributors (see AUTHORS) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/node_modules/acorn/README.md b/node_modules/acorn/README.md new file mode 100644 index 0000000..962de02 --- /dev/null +++ b/node_modules/acorn/README.md @@ -0,0 +1,301 @@ +# Acorn + +A tiny, fast JavaScript parser written in JavaScript. + +## Community + +Acorn is open source software released under an +[MIT license](https://github.com/acornjs/acorn/blob/master/acorn/LICENSE). + +You are welcome to +[report bugs](https://github.com/acornjs/acorn/issues) or create pull +requests on [github](https://github.com/acornjs/acorn). + +## Installation + +The easiest way to install acorn is from [`npm`](https://www.npmjs.com/): + +```sh +npm install acorn +``` + +Alternately, you can download the source and build acorn yourself: + +```sh +git clone https://github.com/acornjs/acorn.git +cd acorn +npm install +``` +## Importing acorn + +ESM as well as CommonJS is supported for all 3: `acorn`, `acorn-walk` and `acorn-loose`. + +ESM example for `acorn`: + +```js +import * as acorn from "acorn" +``` + +CommonJS example for `acorn`: + +```js +let acorn = require("acorn") +``` + +ESM is preferred, as it allows better editor auto-completions by offering TypeScript support. +For this reason, following examples will use ESM imports. + +## Interface + +**parse**`(input, options)` is the main interface to the library. The +`input` parameter is a string, `options` must be an object setting +some of the options listed below. The return value will be an abstract +syntax tree object as specified by the [ESTree +spec](https://github.com/estree/estree). + +```javascript +import * as acorn from "acorn" +console.log(acorn.parse("1 + 1", {ecmaVersion: 2020})) +``` + +When encountering a syntax error, the parser will raise a +`SyntaxError` object with a meaningful message. The error object will +have a `pos` property that indicates the string offset at which the +error occurred, and a `loc` object that contains a `{line, column}` +object referring to that same position. + +Options are provided by in a second argument, which should be an +object containing any of these fields (only `ecmaVersion` is +required): + +- **ecmaVersion**: Indicates the ECMAScript version to parse. Can be a + number, either in year (`2022`) or plain version number (`6`) form, + or `"latest"` (the latest the library supports). This influences + support for strict mode, the set of reserved words, and support for + new syntax features. + + **NOTE**: Only 'stage 4' (finalized) ECMAScript features are being + implemented by Acorn. Other proposed new features must be + implemented through plugins. + +- **sourceType**: Indicate the mode the code should be parsed in. Can be + either `"script"`, `"module"` or `"commonjs"`. This influences global strict mode + and parsing of `import` and `export` declarations. + + **NOTE**: If set to `"module"`, then static `import` / `export` syntax + will be valid, even if `ecmaVersion` is less than 6. If set to `"commonjs"`, + it is the same as `"script"` except that the top-level scope behaves like a function. + +- **onInsertedSemicolon**: If given a callback, that callback will be + called whenever a missing semicolon is inserted by the parser. The + callback will be given the character offset of the point where the + semicolon is inserted as argument, and if `locations` is on, also a + `{line, column}` object representing this position. + +- **onTrailingComma**: Like `onInsertedSemicolon`, but for trailing + commas. + +- **allowReserved**: If `false`, using a reserved word will generate + an error. Defaults to `true` for `ecmaVersion` 3, `false` for higher + versions. When given the value `"never"`, reserved words and + keywords can also not be used as property names (as in Internet + Explorer's old parser). + +- **allowReturnOutsideFunction**: By default, a return statement at + the top level raises an error. Set this to `true` to accept such + code. + +- **allowImportExportEverywhere**: By default, `import` and `export` + declarations can only appear at a program's top level. Setting this + option to `true` allows them anywhere where a statement is allowed, + and also allows `import.meta` expressions to appear in scripts + (when `sourceType` is not `"module"`). + +- **allowAwaitOutsideFunction**: If `false`, `await` expressions can + only appear inside `async` functions. Defaults to `true` in modules + for `ecmaVersion` 2022 and later, `false` for lower versions. + Setting this option to `true` allows to have top-level `await` + expressions. They are still not allowed in non-`async` functions, + though. Setting this option to `true` is not allowed when `sourceType: "commonjs"`. + +- **allowSuperOutsideMethod**: By default, `super` outside a method + raises an error. Set this to `true` to accept such code. + +- **allowHashBang**: When this is enabled, if the code starts with the + characters `#!` (as in a shellscript), the first line will be + treated as a comment. Defaults to true when `ecmaVersion` >= 2023. + +- **checkPrivateFields**: By default, the parser will verify that + private properties are only used in places where they are valid and + have been declared. Set this to false to turn such checks off. + +- **locations**: When `true`, each node has a `loc` object attached + with `start` and `end` subobjects, each of which contains the + one-based line and zero-based column numbers in `{line, column}` + form. Default is `false`. + +- **onToken**: If a function is passed for this option, each found + token will be passed in same format as tokens returned from + `tokenizer().getToken()`. + + If array is passed, each found token is pushed to it. + + Note that you are not allowed to call the parser from the + callback—that will corrupt its internal state. + +- **onComment**: If a function is passed for this option, whenever a + comment is encountered the function will be called with the + following parameters: + + - `block`: `true` if the comment is a block comment, false if it + is a line comment. + - `text`: The content of the comment. + - `start`: Character offset of the start of the comment. + - `end`: Character offset of the end of the comment. + + When the `locations` options is on, the `{line, column}` locations + of the comment’s start and end are passed as two additional + parameters. + + If array is passed for this option, each found comment is pushed + to it as object in Esprima format: + + ```javascript + { + "type": "Line" | "Block", + "value": "comment text", + "start": Number, + "end": Number, + // If `locations` option is on: + "loc": { + "start": {line: Number, column: Number} + "end": {line: Number, column: Number} + }, + // If `ranges` option is on: + "range": [Number, Number] + } + ``` + + Note that you are not allowed to call the parser from the + callback—that will corrupt its internal state. + +- **ranges**: Nodes have their start and end characters offsets + recorded in `start` and `end` properties (directly on the node, + rather than the `loc` object, which holds line/column data. To also + add a + [semi-standardized](https://bugzilla.mozilla.org/show_bug.cgi?id=745678) + `range` property holding a `[start, end]` array with the same + numbers, set the `ranges` option to `true`. + +- **program**: It is possible to parse multiple files into a single + AST by passing the tree produced by parsing the first file as the + `program` option in subsequent parses. This will add the toplevel + forms of the parsed file to the "Program" (top) node of an existing + parse tree. + +- **sourceFile**: When the `locations` option is `true`, you can pass + this option to add a `source` attribute in every node’s `loc` + object. Note that the contents of this option are not examined or + processed in any way; you are free to use whatever format you + choose. + +- **directSourceFile**: Like `sourceFile`, but a `sourceFile` property + will be added (regardless of the `location` option) directly to the + nodes, rather than the `loc` object. + +- **preserveParens**: If this option is `true`, parenthesized expressions + are represented by (non-standard) `ParenthesizedExpression` nodes + that have a single `expression` property containing the expression + inside parentheses. + +**parseExpressionAt**`(input, offset, options)` will parse a single +expression in a string, and return its AST. It will not complain if +there is more of the string left after the expression. + +**tokenizer**`(input, options)` returns an object with a `getToken` +method that can be called repeatedly to get the next token, a `{start, +end, type, value}` object (with added `loc` property when the +`locations` option is enabled and `range` property when the `ranges` +option is enabled). When the token's type is `tokTypes.eof`, you +should stop calling the method, since it will keep returning that same +token forever. + +Note that tokenizing JavaScript without parsing it is, in modern +versions of the language, not really possible due to the way syntax is +overloaded in ways that can only be disambiguated by the parse +context. This package applies a bunch of heuristics to try and do a +reasonable job, but you are advised to use `parse` with the `onToken` +option instead of this. + +In ES6 environment, returned result can be used as any other +protocol-compliant iterable: + +```javascript +for (let token of acorn.tokenizer(str)) { + // iterate over the tokens +} + +// transform code to array of tokens: +var tokens = [...acorn.tokenizer(str)] +``` + +**tokTypes** holds an object mapping names to the token type objects +that end up in the `type` properties of tokens. + +**getLineInfo**`(input, offset)` can be used to get a `{line, +column}` object for a given program string and offset. + +### The `Parser` class + +Instances of the **`Parser`** class contain all the state and logic +that drives a parse. It has static methods `parse`, +`parseExpressionAt`, and `tokenizer` that match the top-level +functions by the same name. + +When extending the parser with plugins, you need to call these methods +on the extended version of the class. To extend a parser with plugins, +you can use its static `extend` method. + +```javascript +var acorn = require("acorn") +var jsx = require("acorn-jsx") +var JSXParser = acorn.Parser.extend(jsx()) +JSXParser.parse("foo()", {ecmaVersion: 2020}) +``` + +The `extend` method takes any number of plugin values, and returns a +new `Parser` class that includes the extra parser logic provided by +the plugins. + +## Command line interface + +The `bin/acorn` utility can be used to parse a file from the command +line. It accepts as arguments its input file and the following +options: + +- `--ecma3|--ecma5|--ecma6|--ecma7|--ecma8|--ecma9|--ecma10`: Sets the ECMAScript version + to parse. Default is version 9. + +- `--module`: Sets the parsing mode to `"module"`. Is set to `"script"` otherwise. + +- `--locations`: Attaches a "loc" object to each node with "start" and + "end" subobjects, each of which contains the one-based line and + zero-based column numbers in `{line, column}` form. + +- `--allow-hash-bang`: If the code starts with the characters #! (as + in a shellscript), the first line will be treated as a comment. + +- `--allow-await-outside-function`: Allows top-level `await` expressions. + See the `allowAwaitOutsideFunction` option for more information. + +- `--compact`: No whitespace is used in the AST output. + +- `--silent`: Do not output the AST, just return the exit status. + +- `--help`: Print the usage information and quit. + +The utility spits out the syntax tree as JSON data. + +## Existing plugins + + - [`acorn-jsx`](https://github.com/RReverser/acorn-jsx): Parse [Facebook JSX syntax extensions](https://github.com/facebook/jsx) diff --git a/node_modules/acorn/bin/acorn b/node_modules/acorn/bin/acorn new file mode 100755 index 0000000..3ef3c12 --- /dev/null +++ b/node_modules/acorn/bin/acorn @@ -0,0 +1,4 @@ +#!/usr/bin/env node +"use strict" + +require("../dist/bin.js") diff --git a/node_modules/acorn/dist/acorn.d.mts b/node_modules/acorn/dist/acorn.d.mts new file mode 100644 index 0000000..afbd913 --- /dev/null +++ b/node_modules/acorn/dist/acorn.d.mts @@ -0,0 +1,883 @@ +export interface Node { + start: number + end: number + type: string + range?: [number, number] + loc?: SourceLocation | null +} + +export interface SourceLocation { + source?: string | null + start: Position + end: Position +} + +export interface Position { + /** 1-based */ + line: number + /** 0-based */ + column: number +} + +export interface Identifier extends Node { + type: "Identifier" + name: string +} + +export interface Literal extends Node { + type: "Literal" + value?: string | boolean | null | number | RegExp | bigint + raw?: string + regex?: { + pattern: string + flags: string + } + bigint?: string +} + +export interface Program extends Node { + type: "Program" + body: Array + sourceType: "script" | "module" +} + +export interface Function extends Node { + id?: Identifier | null + params: Array + body: BlockStatement | Expression + generator: boolean + expression: boolean + async: boolean +} + +export interface ExpressionStatement extends Node { + type: "ExpressionStatement" + expression: Expression | Literal + directive?: string +} + +export interface BlockStatement extends Node { + type: "BlockStatement" + body: Array +} + +export interface EmptyStatement extends Node { + type: "EmptyStatement" +} + +export interface DebuggerStatement extends Node { + type: "DebuggerStatement" +} + +export interface WithStatement extends Node { + type: "WithStatement" + object: Expression + body: Statement +} + +export interface ReturnStatement extends Node { + type: "ReturnStatement" + argument?: Expression | null +} + +export interface LabeledStatement extends Node { + type: "LabeledStatement" + label: Identifier + body: Statement +} + +export interface BreakStatement extends Node { + type: "BreakStatement" + label?: Identifier | null +} + +export interface ContinueStatement extends Node { + type: "ContinueStatement" + label?: Identifier | null +} + +export interface IfStatement extends Node { + type: "IfStatement" + test: Expression + consequent: Statement + alternate?: Statement | null +} + +export interface SwitchStatement extends Node { + type: "SwitchStatement" + discriminant: Expression + cases: Array +} + +export interface SwitchCase extends Node { + type: "SwitchCase" + test?: Expression | null + consequent: Array +} + +export interface ThrowStatement extends Node { + type: "ThrowStatement" + argument: Expression +} + +export interface TryStatement extends Node { + type: "TryStatement" + block: BlockStatement + handler?: CatchClause | null + finalizer?: BlockStatement | null +} + +export interface CatchClause extends Node { + type: "CatchClause" + param?: Pattern | null + body: BlockStatement +} + +export interface WhileStatement extends Node { + type: "WhileStatement" + test: Expression + body: Statement +} + +export interface DoWhileStatement extends Node { + type: "DoWhileStatement" + body: Statement + test: Expression +} + +export interface ForStatement extends Node { + type: "ForStatement" + init?: VariableDeclaration | Expression | null + test?: Expression | null + update?: Expression | null + body: Statement +} + +export interface ForInStatement extends Node { + type: "ForInStatement" + left: VariableDeclaration | Pattern + right: Expression + body: Statement +} + +export interface FunctionDeclaration extends Function { + type: "FunctionDeclaration" + id: Identifier + body: BlockStatement +} + +export interface VariableDeclaration extends Node { + type: "VariableDeclaration" + declarations: Array + kind: "var" | "let" | "const" | "using" | "await using" +} + +export interface VariableDeclarator extends Node { + type: "VariableDeclarator" + id: Pattern + init?: Expression | null +} + +export interface ThisExpression extends Node { + type: "ThisExpression" +} + +export interface ArrayExpression extends Node { + type: "ArrayExpression" + elements: Array +} + +export interface ObjectExpression extends Node { + type: "ObjectExpression" + properties: Array +} + +export interface Property extends Node { + type: "Property" + key: Expression + value: Expression + kind: "init" | "get" | "set" + method: boolean + shorthand: boolean + computed: boolean +} + +export interface FunctionExpression extends Function { + type: "FunctionExpression" + body: BlockStatement +} + +export interface UnaryExpression extends Node { + type: "UnaryExpression" + operator: UnaryOperator + prefix: boolean + argument: Expression +} + +export type UnaryOperator = "-" | "+" | "!" | "~" | "typeof" | "void" | "delete" + +export interface UpdateExpression extends Node { + type: "UpdateExpression" + operator: UpdateOperator + argument: Expression + prefix: boolean +} + +export type UpdateOperator = "++" | "--" + +export interface BinaryExpression extends Node { + type: "BinaryExpression" + operator: BinaryOperator + left: Expression | PrivateIdentifier + right: Expression +} + +export type BinaryOperator = "==" | "!=" | "===" | "!==" | "<" | "<=" | ">" | ">=" | "<<" | ">>" | ">>>" | "+" | "-" | "*" | "/" | "%" | "|" | "^" | "&" | "in" | "instanceof" | "**" + +export interface AssignmentExpression extends Node { + type: "AssignmentExpression" + operator: AssignmentOperator + left: Pattern + right: Expression +} + +export type AssignmentOperator = "=" | "+=" | "-=" | "*=" | "/=" | "%=" | "<<=" | ">>=" | ">>>=" | "|=" | "^=" | "&=" | "**=" | "||=" | "&&=" | "??=" + +export interface LogicalExpression extends Node { + type: "LogicalExpression" + operator: LogicalOperator + left: Expression + right: Expression +} + +export type LogicalOperator = "||" | "&&" | "??" + +export interface MemberExpression extends Node { + type: "MemberExpression" + object: Expression | Super + property: Expression | PrivateIdentifier + computed: boolean + optional: boolean +} + +export interface ConditionalExpression extends Node { + type: "ConditionalExpression" + test: Expression + alternate: Expression + consequent: Expression +} + +export interface CallExpression extends Node { + type: "CallExpression" + callee: Expression | Super + arguments: Array + optional: boolean +} + +export interface NewExpression extends Node { + type: "NewExpression" + callee: Expression + arguments: Array +} + +export interface SequenceExpression extends Node { + type: "SequenceExpression" + expressions: Array +} + +export interface ForOfStatement extends Node { + type: "ForOfStatement" + left: VariableDeclaration | Pattern + right: Expression + body: Statement + await: boolean +} + +export interface Super extends Node { + type: "Super" +} + +export interface SpreadElement extends Node { + type: "SpreadElement" + argument: Expression +} + +export interface ArrowFunctionExpression extends Function { + type: "ArrowFunctionExpression" +} + +export interface YieldExpression extends Node { + type: "YieldExpression" + argument?: Expression | null + delegate: boolean +} + +export interface TemplateLiteral extends Node { + type: "TemplateLiteral" + quasis: Array + expressions: Array +} + +export interface TaggedTemplateExpression extends Node { + type: "TaggedTemplateExpression" + tag: Expression + quasi: TemplateLiteral +} + +export interface TemplateElement extends Node { + type: "TemplateElement" + tail: boolean + value: { + cooked?: string | null + raw: string + } +} + +export interface AssignmentProperty extends Node { + type: "Property" + key: Expression + value: Pattern + kind: "init" + method: false + shorthand: boolean + computed: boolean +} + +export interface ObjectPattern extends Node { + type: "ObjectPattern" + properties: Array +} + +export interface ArrayPattern extends Node { + type: "ArrayPattern" + elements: Array +} + +export interface RestElement extends Node { + type: "RestElement" + argument: Pattern +} + +export interface AssignmentPattern extends Node { + type: "AssignmentPattern" + left: Pattern + right: Expression +} + +export interface Class extends Node { + id?: Identifier | null + superClass?: Expression | null + body: ClassBody +} + +export interface ClassBody extends Node { + type: "ClassBody" + body: Array +} + +export interface MethodDefinition extends Node { + type: "MethodDefinition" + key: Expression | PrivateIdentifier + value: FunctionExpression + kind: "constructor" | "method" | "get" | "set" + computed: boolean + static: boolean +} + +export interface ClassDeclaration extends Class { + type: "ClassDeclaration" + id: Identifier +} + +export interface ClassExpression extends Class { + type: "ClassExpression" +} + +export interface MetaProperty extends Node { + type: "MetaProperty" + meta: Identifier + property: Identifier +} + +export interface ImportDeclaration extends Node { + type: "ImportDeclaration" + specifiers: Array + source: Literal + attributes: Array +} + +export interface ImportSpecifier extends Node { + type: "ImportSpecifier" + imported: Identifier | Literal + local: Identifier +} + +export interface ImportDefaultSpecifier extends Node { + type: "ImportDefaultSpecifier" + local: Identifier +} + +export interface ImportNamespaceSpecifier extends Node { + type: "ImportNamespaceSpecifier" + local: Identifier +} + +export interface ImportAttribute extends Node { + type: "ImportAttribute" + key: Identifier | Literal + value: Literal +} + +export interface ExportNamedDeclaration extends Node { + type: "ExportNamedDeclaration" + declaration?: Declaration | null + specifiers: Array + source?: Literal | null + attributes: Array +} + +export interface ExportSpecifier extends Node { + type: "ExportSpecifier" + exported: Identifier | Literal + local: Identifier | Literal +} + +export interface AnonymousFunctionDeclaration extends Function { + type: "FunctionDeclaration" + id: null + body: BlockStatement +} + +export interface AnonymousClassDeclaration extends Class { + type: "ClassDeclaration" + id: null +} + +export interface ExportDefaultDeclaration extends Node { + type: "ExportDefaultDeclaration" + declaration: AnonymousFunctionDeclaration | FunctionDeclaration | AnonymousClassDeclaration | ClassDeclaration | Expression +} + +export interface ExportAllDeclaration extends Node { + type: "ExportAllDeclaration" + source: Literal + exported?: Identifier | Literal | null + attributes: Array +} + +export interface AwaitExpression extends Node { + type: "AwaitExpression" + argument: Expression +} + +export interface ChainExpression extends Node { + type: "ChainExpression" + expression: MemberExpression | CallExpression +} + +export interface ImportExpression extends Node { + type: "ImportExpression" + source: Expression + options: Expression | null +} + +export interface ParenthesizedExpression extends Node { + type: "ParenthesizedExpression" + expression: Expression +} + +export interface PropertyDefinition extends Node { + type: "PropertyDefinition" + key: Expression | PrivateIdentifier + value?: Expression | null + computed: boolean + static: boolean +} + +export interface PrivateIdentifier extends Node { + type: "PrivateIdentifier" + name: string +} + +export interface StaticBlock extends Node { + type: "StaticBlock" + body: Array +} + +export type Statement = +| ExpressionStatement +| BlockStatement +| EmptyStatement +| DebuggerStatement +| WithStatement +| ReturnStatement +| LabeledStatement +| BreakStatement +| ContinueStatement +| IfStatement +| SwitchStatement +| ThrowStatement +| TryStatement +| WhileStatement +| DoWhileStatement +| ForStatement +| ForInStatement +| ForOfStatement +| Declaration + +export type Declaration = +| FunctionDeclaration +| VariableDeclaration +| ClassDeclaration + +export type Expression = +| Identifier +| Literal +| ThisExpression +| ArrayExpression +| ObjectExpression +| FunctionExpression +| UnaryExpression +| UpdateExpression +| BinaryExpression +| AssignmentExpression +| LogicalExpression +| MemberExpression +| ConditionalExpression +| CallExpression +| NewExpression +| SequenceExpression +| ArrowFunctionExpression +| YieldExpression +| TemplateLiteral +| TaggedTemplateExpression +| ClassExpression +| MetaProperty +| AwaitExpression +| ChainExpression +| ImportExpression +| ParenthesizedExpression + +export type Pattern = +| Identifier +| MemberExpression +| ObjectPattern +| ArrayPattern +| RestElement +| AssignmentPattern + +export type ModuleDeclaration = +| ImportDeclaration +| ExportNamedDeclaration +| ExportDefaultDeclaration +| ExportAllDeclaration + +/** + * This interface is only used for defining {@link AnyNode}. + * It exists so that it can be extended by plugins: + * + * @example + * ```typescript + * declare module 'acorn' { + * interface NodeTypes { + * pluginName: FirstNode | SecondNode | ThirdNode | ... | LastNode + * } + * } + * ``` + */ +interface NodeTypes { + core: Statement | Expression | Declaration | ModuleDeclaration | Literal | Program | SwitchCase | CatchClause | Property | Super | SpreadElement | TemplateElement | AssignmentProperty | ObjectPattern | ArrayPattern | RestElement | AssignmentPattern | ClassBody | MethodDefinition | MetaProperty | ImportAttribute | ImportSpecifier | ImportDefaultSpecifier | ImportNamespaceSpecifier | ExportSpecifier | AnonymousFunctionDeclaration | AnonymousClassDeclaration | PropertyDefinition | PrivateIdentifier | StaticBlock | VariableDeclarator +} + +export type AnyNode = NodeTypes[keyof NodeTypes] + +export function parse(input: string, options: Options): Program + +export function parseExpressionAt(input: string, pos: number, options: Options): Expression + +export function tokenizer(input: string, options: Options): { + getToken(): Token + [Symbol.iterator](): Iterator +} + +export type ecmaVersion = 3 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 2015 | 2016 | 2017 | 2018 | 2019 | 2020 | 2021 | 2022 | 2023 | 2024 | 2025 | 2026 | "latest" + +export interface Options { + /** + * `ecmaVersion` indicates the ECMAScript version to parse. Can be a + * number, either in year (`2022`) or plain version number (`6`) form, + * or `"latest"` (the latest the library supports). This influences + * support for strict mode, the set of reserved words, and support for + * new syntax features. + */ + ecmaVersion: ecmaVersion + + /** + * `sourceType` indicates the mode the code should be parsed in. + * Can be either `"script"`, `"module"` or `"commonjs"`. This influences global + * strict mode and parsing of `import` and `export` declarations. + */ + sourceType?: "script" | "module" | "commonjs" + + /** + * a callback that will be called when a semicolon is automatically inserted. + * @param lastTokEnd the position of the comma as an offset + * @param lastTokEndLoc location if {@link locations} is enabled + */ + onInsertedSemicolon?: (lastTokEnd: number, lastTokEndLoc?: Position) => void + + /** + * similar to `onInsertedSemicolon`, but for trailing commas + * @param lastTokEnd the position of the comma as an offset + * @param lastTokEndLoc location if `locations` is enabled + */ + onTrailingComma?: (lastTokEnd: number, lastTokEndLoc?: Position) => void + + /** + * By default, reserved words are only enforced if ecmaVersion >= 5. + * Set `allowReserved` to a boolean value to explicitly turn this on + * an off. When this option has the value "never", reserved words + * and keywords can also not be used as property names. + */ + allowReserved?: boolean | "never" + + /** + * When enabled, a return at the top level is not considered an error. + */ + allowReturnOutsideFunction?: boolean + + /** + * When enabled, import/export statements are not constrained to + * appearing at the top of the program, and an import.meta expression + * in a script isn't considered an error. + */ + allowImportExportEverywhere?: boolean + + /** + * By default, `await` identifiers are allowed to appear at the top-level scope only if {@link ecmaVersion} >= 2022. + * When enabled, await identifiers are allowed to appear at the top-level scope, + * but they are still not allowed in non-async functions. + */ + allowAwaitOutsideFunction?: boolean + + /** + * When enabled, super identifiers are not constrained to + * appearing in methods and do not raise an error when they appear elsewhere. + */ + allowSuperOutsideMethod?: boolean + + /** + * When enabled, hashbang directive in the beginning of file is + * allowed and treated as a line comment. Enabled by default when + * {@link ecmaVersion} >= 2023. + */ + allowHashBang?: boolean + + /** + * By default, the parser will verify that private properties are + * only used in places where they are valid and have been declared. + * Set this to false to turn such checks off. + */ + checkPrivateFields?: boolean + + /** + * When `locations` is on, `loc` properties holding objects with + * `start` and `end` properties as {@link Position} objects will be attached to the + * nodes. + */ + locations?: boolean + + /** + * a callback that will cause Acorn to call that export function with object in the same + * format as tokens returned from `tokenizer().getToken()`. Note + * that you are not allowed to call the parser from the + * callback—that will corrupt its internal state. + */ + onToken?: ((token: Token) => void) | Token[] + + + /** + * This takes a export function or an array. + * + * When a export function is passed, Acorn will call that export function with `(block, text, start, + * end)` parameters whenever a comment is skipped. `block` is a + * boolean indicating whether this is a block (`/* *\/`) comment, + * `text` is the content of the comment, and `start` and `end` are + * character offsets that denote the start and end of the comment. + * When the {@link locations} option is on, two more parameters are + * passed, the full locations of {@link Position} export type of the start and + * end of the comments. + * + * When a array is passed, each found comment of {@link Comment} export type is pushed to the array. + * + * Note that you are not allowed to call the + * parser from the callback—that will corrupt its internal state. + */ + onComment?: (( + isBlock: boolean, text: string, start: number, end: number, startLoc?: Position, + endLoc?: Position + ) => void) | Comment[] + + /** + * Nodes have their start and end characters offsets recorded in + * `start` and `end` properties (directly on the node, rather than + * the `loc` object, which holds line/column data. To also add a + * [semi-standardized][range] `range` property holding a `[start, + * end]` array with the same numbers, set the `ranges` option to + * `true`. + */ + ranges?: boolean + + /** + * It is possible to parse multiple files into a single AST by + * passing the tree produced by parsing the first file as + * `program` option in subsequent parses. This will add the + * toplevel forms of the parsed file to the `Program` (top) node + * of an existing parse tree. + */ + program?: Node + + /** + * When {@link locations} is on, you can pass this to record the source + * file in every node's `loc` object. + */ + sourceFile?: string + + /** + * This value, if given, is stored in every node, whether {@link locations} is on or off. + */ + directSourceFile?: string + + /** + * When enabled, parenthesized expressions are represented by + * (non-standard) ParenthesizedExpression nodes + */ + preserveParens?: boolean +} + +export class Parser { + options: Options + input: string + + protected constructor(options: Options, input: string, startPos?: number) + parse(): Program + + static parse(input: string, options: Options): Program + static parseExpressionAt(input: string, pos: number, options: Options): Expression + static tokenizer(input: string, options: Options): { + getToken(): Token + [Symbol.iterator](): Iterator + } + static extend(...plugins: ((BaseParser: typeof Parser) => typeof Parser)[]): typeof Parser +} + +export const defaultOptions: Options + +export function getLineInfo(input: string, offset: number): Position + +export class TokenType { + label: string + keyword: string | undefined +} + +export const tokTypes: { + num: TokenType + regexp: TokenType + string: TokenType + name: TokenType + privateId: TokenType + eof: TokenType + + bracketL: TokenType + bracketR: TokenType + braceL: TokenType + braceR: TokenType + parenL: TokenType + parenR: TokenType + comma: TokenType + semi: TokenType + colon: TokenType + dot: TokenType + question: TokenType + questionDot: TokenType + arrow: TokenType + template: TokenType + invalidTemplate: TokenType + ellipsis: TokenType + backQuote: TokenType + dollarBraceL: TokenType + + eq: TokenType + assign: TokenType + incDec: TokenType + prefix: TokenType + logicalOR: TokenType + logicalAND: TokenType + bitwiseOR: TokenType + bitwiseXOR: TokenType + bitwiseAND: TokenType + equality: TokenType + relational: TokenType + bitShift: TokenType + plusMin: TokenType + modulo: TokenType + star: TokenType + slash: TokenType + starstar: TokenType + coalesce: TokenType + + _break: TokenType + _case: TokenType + _catch: TokenType + _continue: TokenType + _debugger: TokenType + _default: TokenType + _do: TokenType + _else: TokenType + _finally: TokenType + _for: TokenType + _function: TokenType + _if: TokenType + _return: TokenType + _switch: TokenType + _throw: TokenType + _try: TokenType + _var: TokenType + _const: TokenType + _while: TokenType + _with: TokenType + _new: TokenType + _this: TokenType + _super: TokenType + _class: TokenType + _extends: TokenType + _export: TokenType + _import: TokenType + _null: TokenType + _true: TokenType + _false: TokenType + _in: TokenType + _instanceof: TokenType + _typeof: TokenType + _void: TokenType + _delete: TokenType +} + +export interface Comment { + type: "Line" | "Block" + value: string + start: number + end: number + loc?: SourceLocation + range?: [number, number] +} + +export class Token { + type: TokenType + start: number + end: number + loc?: SourceLocation + range?: [number, number] +} + +export const version: string diff --git a/node_modules/acorn/dist/acorn.d.ts b/node_modules/acorn/dist/acorn.d.ts new file mode 100644 index 0000000..afbd913 --- /dev/null +++ b/node_modules/acorn/dist/acorn.d.ts @@ -0,0 +1,883 @@ +export interface Node { + start: number + end: number + type: string + range?: [number, number] + loc?: SourceLocation | null +} + +export interface SourceLocation { + source?: string | null + start: Position + end: Position +} + +export interface Position { + /** 1-based */ + line: number + /** 0-based */ + column: number +} + +export interface Identifier extends Node { + type: "Identifier" + name: string +} + +export interface Literal extends Node { + type: "Literal" + value?: string | boolean | null | number | RegExp | bigint + raw?: string + regex?: { + pattern: string + flags: string + } + bigint?: string +} + +export interface Program extends Node { + type: "Program" + body: Array + sourceType: "script" | "module" +} + +export interface Function extends Node { + id?: Identifier | null + params: Array + body: BlockStatement | Expression + generator: boolean + expression: boolean + async: boolean +} + +export interface ExpressionStatement extends Node { + type: "ExpressionStatement" + expression: Expression | Literal + directive?: string +} + +export interface BlockStatement extends Node { + type: "BlockStatement" + body: Array +} + +export interface EmptyStatement extends Node { + type: "EmptyStatement" +} + +export interface DebuggerStatement extends Node { + type: "DebuggerStatement" +} + +export interface WithStatement extends Node { + type: "WithStatement" + object: Expression + body: Statement +} + +export interface ReturnStatement extends Node { + type: "ReturnStatement" + argument?: Expression | null +} + +export interface LabeledStatement extends Node { + type: "LabeledStatement" + label: Identifier + body: Statement +} + +export interface BreakStatement extends Node { + type: "BreakStatement" + label?: Identifier | null +} + +export interface ContinueStatement extends Node { + type: "ContinueStatement" + label?: Identifier | null +} + +export interface IfStatement extends Node { + type: "IfStatement" + test: Expression + consequent: Statement + alternate?: Statement | null +} + +export interface SwitchStatement extends Node { + type: "SwitchStatement" + discriminant: Expression + cases: Array +} + +export interface SwitchCase extends Node { + type: "SwitchCase" + test?: Expression | null + consequent: Array +} + +export interface ThrowStatement extends Node { + type: "ThrowStatement" + argument: Expression +} + +export interface TryStatement extends Node { + type: "TryStatement" + block: BlockStatement + handler?: CatchClause | null + finalizer?: BlockStatement | null +} + +export interface CatchClause extends Node { + type: "CatchClause" + param?: Pattern | null + body: BlockStatement +} + +export interface WhileStatement extends Node { + type: "WhileStatement" + test: Expression + body: Statement +} + +export interface DoWhileStatement extends Node { + type: "DoWhileStatement" + body: Statement + test: Expression +} + +export interface ForStatement extends Node { + type: "ForStatement" + init?: VariableDeclaration | Expression | null + test?: Expression | null + update?: Expression | null + body: Statement +} + +export interface ForInStatement extends Node { + type: "ForInStatement" + left: VariableDeclaration | Pattern + right: Expression + body: Statement +} + +export interface FunctionDeclaration extends Function { + type: "FunctionDeclaration" + id: Identifier + body: BlockStatement +} + +export interface VariableDeclaration extends Node { + type: "VariableDeclaration" + declarations: Array + kind: "var" | "let" | "const" | "using" | "await using" +} + +export interface VariableDeclarator extends Node { + type: "VariableDeclarator" + id: Pattern + init?: Expression | null +} + +export interface ThisExpression extends Node { + type: "ThisExpression" +} + +export interface ArrayExpression extends Node { + type: "ArrayExpression" + elements: Array +} + +export interface ObjectExpression extends Node { + type: "ObjectExpression" + properties: Array +} + +export interface Property extends Node { + type: "Property" + key: Expression + value: Expression + kind: "init" | "get" | "set" + method: boolean + shorthand: boolean + computed: boolean +} + +export interface FunctionExpression extends Function { + type: "FunctionExpression" + body: BlockStatement +} + +export interface UnaryExpression extends Node { + type: "UnaryExpression" + operator: UnaryOperator + prefix: boolean + argument: Expression +} + +export type UnaryOperator = "-" | "+" | "!" | "~" | "typeof" | "void" | "delete" + +export interface UpdateExpression extends Node { + type: "UpdateExpression" + operator: UpdateOperator + argument: Expression + prefix: boolean +} + +export type UpdateOperator = "++" | "--" + +export interface BinaryExpression extends Node { + type: "BinaryExpression" + operator: BinaryOperator + left: Expression | PrivateIdentifier + right: Expression +} + +export type BinaryOperator = "==" | "!=" | "===" | "!==" | "<" | "<=" | ">" | ">=" | "<<" | ">>" | ">>>" | "+" | "-" | "*" | "/" | "%" | "|" | "^" | "&" | "in" | "instanceof" | "**" + +export interface AssignmentExpression extends Node { + type: "AssignmentExpression" + operator: AssignmentOperator + left: Pattern + right: Expression +} + +export type AssignmentOperator = "=" | "+=" | "-=" | "*=" | "/=" | "%=" | "<<=" | ">>=" | ">>>=" | "|=" | "^=" | "&=" | "**=" | "||=" | "&&=" | "??=" + +export interface LogicalExpression extends Node { + type: "LogicalExpression" + operator: LogicalOperator + left: Expression + right: Expression +} + +export type LogicalOperator = "||" | "&&" | "??" + +export interface MemberExpression extends Node { + type: "MemberExpression" + object: Expression | Super + property: Expression | PrivateIdentifier + computed: boolean + optional: boolean +} + +export interface ConditionalExpression extends Node { + type: "ConditionalExpression" + test: Expression + alternate: Expression + consequent: Expression +} + +export interface CallExpression extends Node { + type: "CallExpression" + callee: Expression | Super + arguments: Array + optional: boolean +} + +export interface NewExpression extends Node { + type: "NewExpression" + callee: Expression + arguments: Array +} + +export interface SequenceExpression extends Node { + type: "SequenceExpression" + expressions: Array +} + +export interface ForOfStatement extends Node { + type: "ForOfStatement" + left: VariableDeclaration | Pattern + right: Expression + body: Statement + await: boolean +} + +export interface Super extends Node { + type: "Super" +} + +export interface SpreadElement extends Node { + type: "SpreadElement" + argument: Expression +} + +export interface ArrowFunctionExpression extends Function { + type: "ArrowFunctionExpression" +} + +export interface YieldExpression extends Node { + type: "YieldExpression" + argument?: Expression | null + delegate: boolean +} + +export interface TemplateLiteral extends Node { + type: "TemplateLiteral" + quasis: Array + expressions: Array +} + +export interface TaggedTemplateExpression extends Node { + type: "TaggedTemplateExpression" + tag: Expression + quasi: TemplateLiteral +} + +export interface TemplateElement extends Node { + type: "TemplateElement" + tail: boolean + value: { + cooked?: string | null + raw: string + } +} + +export interface AssignmentProperty extends Node { + type: "Property" + key: Expression + value: Pattern + kind: "init" + method: false + shorthand: boolean + computed: boolean +} + +export interface ObjectPattern extends Node { + type: "ObjectPattern" + properties: Array +} + +export interface ArrayPattern extends Node { + type: "ArrayPattern" + elements: Array +} + +export interface RestElement extends Node { + type: "RestElement" + argument: Pattern +} + +export interface AssignmentPattern extends Node { + type: "AssignmentPattern" + left: Pattern + right: Expression +} + +export interface Class extends Node { + id?: Identifier | null + superClass?: Expression | null + body: ClassBody +} + +export interface ClassBody extends Node { + type: "ClassBody" + body: Array +} + +export interface MethodDefinition extends Node { + type: "MethodDefinition" + key: Expression | PrivateIdentifier + value: FunctionExpression + kind: "constructor" | "method" | "get" | "set" + computed: boolean + static: boolean +} + +export interface ClassDeclaration extends Class { + type: "ClassDeclaration" + id: Identifier +} + +export interface ClassExpression extends Class { + type: "ClassExpression" +} + +export interface MetaProperty extends Node { + type: "MetaProperty" + meta: Identifier + property: Identifier +} + +export interface ImportDeclaration extends Node { + type: "ImportDeclaration" + specifiers: Array + source: Literal + attributes: Array +} + +export interface ImportSpecifier extends Node { + type: "ImportSpecifier" + imported: Identifier | Literal + local: Identifier +} + +export interface ImportDefaultSpecifier extends Node { + type: "ImportDefaultSpecifier" + local: Identifier +} + +export interface ImportNamespaceSpecifier extends Node { + type: "ImportNamespaceSpecifier" + local: Identifier +} + +export interface ImportAttribute extends Node { + type: "ImportAttribute" + key: Identifier | Literal + value: Literal +} + +export interface ExportNamedDeclaration extends Node { + type: "ExportNamedDeclaration" + declaration?: Declaration | null + specifiers: Array + source?: Literal | null + attributes: Array +} + +export interface ExportSpecifier extends Node { + type: "ExportSpecifier" + exported: Identifier | Literal + local: Identifier | Literal +} + +export interface AnonymousFunctionDeclaration extends Function { + type: "FunctionDeclaration" + id: null + body: BlockStatement +} + +export interface AnonymousClassDeclaration extends Class { + type: "ClassDeclaration" + id: null +} + +export interface ExportDefaultDeclaration extends Node { + type: "ExportDefaultDeclaration" + declaration: AnonymousFunctionDeclaration | FunctionDeclaration | AnonymousClassDeclaration | ClassDeclaration | Expression +} + +export interface ExportAllDeclaration extends Node { + type: "ExportAllDeclaration" + source: Literal + exported?: Identifier | Literal | null + attributes: Array +} + +export interface AwaitExpression extends Node { + type: "AwaitExpression" + argument: Expression +} + +export interface ChainExpression extends Node { + type: "ChainExpression" + expression: MemberExpression | CallExpression +} + +export interface ImportExpression extends Node { + type: "ImportExpression" + source: Expression + options: Expression | null +} + +export interface ParenthesizedExpression extends Node { + type: "ParenthesizedExpression" + expression: Expression +} + +export interface PropertyDefinition extends Node { + type: "PropertyDefinition" + key: Expression | PrivateIdentifier + value?: Expression | null + computed: boolean + static: boolean +} + +export interface PrivateIdentifier extends Node { + type: "PrivateIdentifier" + name: string +} + +export interface StaticBlock extends Node { + type: "StaticBlock" + body: Array +} + +export type Statement = +| ExpressionStatement +| BlockStatement +| EmptyStatement +| DebuggerStatement +| WithStatement +| ReturnStatement +| LabeledStatement +| BreakStatement +| ContinueStatement +| IfStatement +| SwitchStatement +| ThrowStatement +| TryStatement +| WhileStatement +| DoWhileStatement +| ForStatement +| ForInStatement +| ForOfStatement +| Declaration + +export type Declaration = +| FunctionDeclaration +| VariableDeclaration +| ClassDeclaration + +export type Expression = +| Identifier +| Literal +| ThisExpression +| ArrayExpression +| ObjectExpression +| FunctionExpression +| UnaryExpression +| UpdateExpression +| BinaryExpression +| AssignmentExpression +| LogicalExpression +| MemberExpression +| ConditionalExpression +| CallExpression +| NewExpression +| SequenceExpression +| ArrowFunctionExpression +| YieldExpression +| TemplateLiteral +| TaggedTemplateExpression +| ClassExpression +| MetaProperty +| AwaitExpression +| ChainExpression +| ImportExpression +| ParenthesizedExpression + +export type Pattern = +| Identifier +| MemberExpression +| ObjectPattern +| ArrayPattern +| RestElement +| AssignmentPattern + +export type ModuleDeclaration = +| ImportDeclaration +| ExportNamedDeclaration +| ExportDefaultDeclaration +| ExportAllDeclaration + +/** + * This interface is only used for defining {@link AnyNode}. + * It exists so that it can be extended by plugins: + * + * @example + * ```typescript + * declare module 'acorn' { + * interface NodeTypes { + * pluginName: FirstNode | SecondNode | ThirdNode | ... | LastNode + * } + * } + * ``` + */ +interface NodeTypes { + core: Statement | Expression | Declaration | ModuleDeclaration | Literal | Program | SwitchCase | CatchClause | Property | Super | SpreadElement | TemplateElement | AssignmentProperty | ObjectPattern | ArrayPattern | RestElement | AssignmentPattern | ClassBody | MethodDefinition | MetaProperty | ImportAttribute | ImportSpecifier | ImportDefaultSpecifier | ImportNamespaceSpecifier | ExportSpecifier | AnonymousFunctionDeclaration | AnonymousClassDeclaration | PropertyDefinition | PrivateIdentifier | StaticBlock | VariableDeclarator +} + +export type AnyNode = NodeTypes[keyof NodeTypes] + +export function parse(input: string, options: Options): Program + +export function parseExpressionAt(input: string, pos: number, options: Options): Expression + +export function tokenizer(input: string, options: Options): { + getToken(): Token + [Symbol.iterator](): Iterator +} + +export type ecmaVersion = 3 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 2015 | 2016 | 2017 | 2018 | 2019 | 2020 | 2021 | 2022 | 2023 | 2024 | 2025 | 2026 | "latest" + +export interface Options { + /** + * `ecmaVersion` indicates the ECMAScript version to parse. Can be a + * number, either in year (`2022`) or plain version number (`6`) form, + * or `"latest"` (the latest the library supports). This influences + * support for strict mode, the set of reserved words, and support for + * new syntax features. + */ + ecmaVersion: ecmaVersion + + /** + * `sourceType` indicates the mode the code should be parsed in. + * Can be either `"script"`, `"module"` or `"commonjs"`. This influences global + * strict mode and parsing of `import` and `export` declarations. + */ + sourceType?: "script" | "module" | "commonjs" + + /** + * a callback that will be called when a semicolon is automatically inserted. + * @param lastTokEnd the position of the comma as an offset + * @param lastTokEndLoc location if {@link locations} is enabled + */ + onInsertedSemicolon?: (lastTokEnd: number, lastTokEndLoc?: Position) => void + + /** + * similar to `onInsertedSemicolon`, but for trailing commas + * @param lastTokEnd the position of the comma as an offset + * @param lastTokEndLoc location if `locations` is enabled + */ + onTrailingComma?: (lastTokEnd: number, lastTokEndLoc?: Position) => void + + /** + * By default, reserved words are only enforced if ecmaVersion >= 5. + * Set `allowReserved` to a boolean value to explicitly turn this on + * an off. When this option has the value "never", reserved words + * and keywords can also not be used as property names. + */ + allowReserved?: boolean | "never" + + /** + * When enabled, a return at the top level is not considered an error. + */ + allowReturnOutsideFunction?: boolean + + /** + * When enabled, import/export statements are not constrained to + * appearing at the top of the program, and an import.meta expression + * in a script isn't considered an error. + */ + allowImportExportEverywhere?: boolean + + /** + * By default, `await` identifiers are allowed to appear at the top-level scope only if {@link ecmaVersion} >= 2022. + * When enabled, await identifiers are allowed to appear at the top-level scope, + * but they are still not allowed in non-async functions. + */ + allowAwaitOutsideFunction?: boolean + + /** + * When enabled, super identifiers are not constrained to + * appearing in methods and do not raise an error when they appear elsewhere. + */ + allowSuperOutsideMethod?: boolean + + /** + * When enabled, hashbang directive in the beginning of file is + * allowed and treated as a line comment. Enabled by default when + * {@link ecmaVersion} >= 2023. + */ + allowHashBang?: boolean + + /** + * By default, the parser will verify that private properties are + * only used in places where they are valid and have been declared. + * Set this to false to turn such checks off. + */ + checkPrivateFields?: boolean + + /** + * When `locations` is on, `loc` properties holding objects with + * `start` and `end` properties as {@link Position} objects will be attached to the + * nodes. + */ + locations?: boolean + + /** + * a callback that will cause Acorn to call that export function with object in the same + * format as tokens returned from `tokenizer().getToken()`. Note + * that you are not allowed to call the parser from the + * callback—that will corrupt its internal state. + */ + onToken?: ((token: Token) => void) | Token[] + + + /** + * This takes a export function or an array. + * + * When a export function is passed, Acorn will call that export function with `(block, text, start, + * end)` parameters whenever a comment is skipped. `block` is a + * boolean indicating whether this is a block (`/* *\/`) comment, + * `text` is the content of the comment, and `start` and `end` are + * character offsets that denote the start and end of the comment. + * When the {@link locations} option is on, two more parameters are + * passed, the full locations of {@link Position} export type of the start and + * end of the comments. + * + * When a array is passed, each found comment of {@link Comment} export type is pushed to the array. + * + * Note that you are not allowed to call the + * parser from the callback—that will corrupt its internal state. + */ + onComment?: (( + isBlock: boolean, text: string, start: number, end: number, startLoc?: Position, + endLoc?: Position + ) => void) | Comment[] + + /** + * Nodes have their start and end characters offsets recorded in + * `start` and `end` properties (directly on the node, rather than + * the `loc` object, which holds line/column data. To also add a + * [semi-standardized][range] `range` property holding a `[start, + * end]` array with the same numbers, set the `ranges` option to + * `true`. + */ + ranges?: boolean + + /** + * It is possible to parse multiple files into a single AST by + * passing the tree produced by parsing the first file as + * `program` option in subsequent parses. This will add the + * toplevel forms of the parsed file to the `Program` (top) node + * of an existing parse tree. + */ + program?: Node + + /** + * When {@link locations} is on, you can pass this to record the source + * file in every node's `loc` object. + */ + sourceFile?: string + + /** + * This value, if given, is stored in every node, whether {@link locations} is on or off. + */ + directSourceFile?: string + + /** + * When enabled, parenthesized expressions are represented by + * (non-standard) ParenthesizedExpression nodes + */ + preserveParens?: boolean +} + +export class Parser { + options: Options + input: string + + protected constructor(options: Options, input: string, startPos?: number) + parse(): Program + + static parse(input: string, options: Options): Program + static parseExpressionAt(input: string, pos: number, options: Options): Expression + static tokenizer(input: string, options: Options): { + getToken(): Token + [Symbol.iterator](): Iterator + } + static extend(...plugins: ((BaseParser: typeof Parser) => typeof Parser)[]): typeof Parser +} + +export const defaultOptions: Options + +export function getLineInfo(input: string, offset: number): Position + +export class TokenType { + label: string + keyword: string | undefined +} + +export const tokTypes: { + num: TokenType + regexp: TokenType + string: TokenType + name: TokenType + privateId: TokenType + eof: TokenType + + bracketL: TokenType + bracketR: TokenType + braceL: TokenType + braceR: TokenType + parenL: TokenType + parenR: TokenType + comma: TokenType + semi: TokenType + colon: TokenType + dot: TokenType + question: TokenType + questionDot: TokenType + arrow: TokenType + template: TokenType + invalidTemplate: TokenType + ellipsis: TokenType + backQuote: TokenType + dollarBraceL: TokenType + + eq: TokenType + assign: TokenType + incDec: TokenType + prefix: TokenType + logicalOR: TokenType + logicalAND: TokenType + bitwiseOR: TokenType + bitwiseXOR: TokenType + bitwiseAND: TokenType + equality: TokenType + relational: TokenType + bitShift: TokenType + plusMin: TokenType + modulo: TokenType + star: TokenType + slash: TokenType + starstar: TokenType + coalesce: TokenType + + _break: TokenType + _case: TokenType + _catch: TokenType + _continue: TokenType + _debugger: TokenType + _default: TokenType + _do: TokenType + _else: TokenType + _finally: TokenType + _for: TokenType + _function: TokenType + _if: TokenType + _return: TokenType + _switch: TokenType + _throw: TokenType + _try: TokenType + _var: TokenType + _const: TokenType + _while: TokenType + _with: TokenType + _new: TokenType + _this: TokenType + _super: TokenType + _class: TokenType + _extends: TokenType + _export: TokenType + _import: TokenType + _null: TokenType + _true: TokenType + _false: TokenType + _in: TokenType + _instanceof: TokenType + _typeof: TokenType + _void: TokenType + _delete: TokenType +} + +export interface Comment { + type: "Line" | "Block" + value: string + start: number + end: number + loc?: SourceLocation + range?: [number, number] +} + +export class Token { + type: TokenType + start: number + end: number + loc?: SourceLocation + range?: [number, number] +} + +export const version: string diff --git a/node_modules/acorn/dist/acorn.js b/node_modules/acorn/dist/acorn.js new file mode 100644 index 0000000..b4f281a --- /dev/null +++ b/node_modules/acorn/dist/acorn.js @@ -0,0 +1,6295 @@ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : + typeof define === 'function' && define.amd ? define(['exports'], factory) : + (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.acorn = {})); +})(this, (function (exports) { 'use strict'; + + // This file was generated. Do not modify manually! + var astralIdentifierCodes = [509, 0, 227, 0, 150, 4, 294, 9, 1368, 2, 2, 1, 6, 3, 41, 2, 5, 0, 166, 1, 574, 3, 9, 9, 7, 9, 32, 4, 318, 1, 78, 5, 71, 10, 50, 3, 123, 2, 54, 14, 32, 10, 3, 1, 11, 3, 46, 10, 8, 0, 46, 9, 7, 2, 37, 13, 2, 9, 6, 1, 45, 0, 13, 2, 49, 13, 9, 3, 2, 11, 83, 11, 7, 0, 3, 0, 158, 11, 6, 9, 7, 3, 56, 1, 2, 6, 3, 1, 3, 2, 10, 0, 11, 1, 3, 6, 4, 4, 68, 8, 2, 0, 3, 0, 2, 3, 2, 4, 2, 0, 15, 1, 83, 17, 10, 9, 5, 0, 82, 19, 13, 9, 214, 6, 3, 8, 28, 1, 83, 16, 16, 9, 82, 12, 9, 9, 7, 19, 58, 14, 5, 9, 243, 14, 166, 9, 71, 5, 2, 1, 3, 3, 2, 0, 2, 1, 13, 9, 120, 6, 3, 6, 4, 0, 29, 9, 41, 6, 2, 3, 9, 0, 10, 10, 47, 15, 199, 7, 137, 9, 54, 7, 2, 7, 17, 9, 57, 21, 2, 13, 123, 5, 4, 0, 2, 1, 2, 6, 2, 0, 9, 9, 49, 4, 2, 1, 2, 4, 9, 9, 55, 9, 266, 3, 10, 1, 2, 0, 49, 6, 4, 4, 14, 10, 5350, 0, 7, 14, 11465, 27, 2343, 9, 87, 9, 39, 4, 60, 6, 26, 9, 535, 9, 470, 0, 2, 54, 8, 3, 82, 0, 12, 1, 19628, 1, 4178, 9, 519, 45, 3, 22, 543, 4, 4, 5, 9, 7, 3, 6, 31, 3, 149, 2, 1418, 49, 513, 54, 5, 49, 9, 0, 15, 0, 23, 4, 2, 14, 1361, 6, 2, 16, 3, 6, 2, 1, 2, 4, 101, 0, 161, 6, 10, 9, 357, 0, 62, 13, 499, 13, 245, 1, 2, 9, 233, 0, 3, 0, 8, 1, 6, 0, 475, 6, 110, 6, 6, 9, 4759, 9, 787719, 239]; + + // This file was generated. Do not modify manually! + var astralIdentifierStartCodes = [0, 11, 2, 25, 2, 18, 2, 1, 2, 14, 3, 13, 35, 122, 70, 52, 268, 28, 4, 48, 48, 31, 14, 29, 6, 37, 11, 29, 3, 35, 5, 7, 2, 4, 43, 157, 19, 35, 5, 35, 5, 39, 9, 51, 13, 10, 2, 14, 2, 6, 2, 1, 2, 10, 2, 14, 2, 6, 2, 1, 4, 51, 13, 310, 10, 21, 11, 7, 25, 5, 2, 41, 2, 8, 70, 5, 3, 0, 2, 43, 2, 1, 4, 0, 3, 22, 11, 22, 10, 30, 66, 18, 2, 1, 11, 21, 11, 25, 7, 25, 39, 55, 7, 1, 65, 0, 16, 3, 2, 2, 2, 28, 43, 28, 4, 28, 36, 7, 2, 27, 28, 53, 11, 21, 11, 18, 14, 17, 111, 72, 56, 50, 14, 50, 14, 35, 39, 27, 10, 22, 251, 41, 7, 1, 17, 5, 57, 28, 11, 0, 9, 21, 43, 17, 47, 20, 28, 22, 13, 52, 58, 1, 3, 0, 14, 44, 33, 24, 27, 35, 30, 0, 3, 0, 9, 34, 4, 0, 13, 47, 15, 3, 22, 0, 2, 0, 36, 17, 2, 24, 20, 1, 64, 6, 2, 0, 2, 3, 2, 14, 2, 9, 8, 46, 39, 7, 3, 1, 3, 21, 2, 6, 2, 1, 2, 4, 4, 0, 19, 0, 13, 4, 31, 9, 2, 0, 3, 0, 2, 37, 2, 0, 26, 0, 2, 0, 45, 52, 19, 3, 21, 2, 31, 47, 21, 1, 2, 0, 185, 46, 42, 3, 37, 47, 21, 0, 60, 42, 14, 0, 72, 26, 38, 6, 186, 43, 117, 63, 32, 7, 3, 0, 3, 7, 2, 1, 2, 23, 16, 0, 2, 0, 95, 7, 3, 38, 17, 0, 2, 0, 29, 0, 11, 39, 8, 0, 22, 0, 12, 45, 20, 0, 19, 72, 200, 32, 32, 8, 2, 36, 18, 0, 50, 29, 113, 6, 2, 1, 2, 37, 22, 0, 26, 5, 2, 1, 2, 31, 15, 0, 24, 43, 261, 18, 16, 0, 2, 12, 2, 33, 125, 0, 80, 921, 103, 110, 18, 195, 2637, 96, 16, 1071, 18, 5, 26, 3994, 6, 582, 6842, 29, 1763, 568, 8, 30, 18, 78, 18, 29, 19, 47, 17, 3, 32, 20, 6, 18, 433, 44, 212, 63, 33, 24, 3, 24, 45, 74, 6, 0, 67, 12, 65, 1, 2, 0, 15, 4, 10, 7381, 42, 31, 98, 114, 8702, 3, 2, 6, 2, 1, 2, 290, 16, 0, 30, 2, 3, 0, 15, 3, 9, 395, 2309, 106, 6, 12, 4, 8, 8, 9, 5991, 84, 2, 70, 2, 1, 3, 0, 3, 1, 3, 3, 2, 11, 2, 0, 2, 6, 2, 64, 2, 3, 3, 7, 2, 6, 2, 27, 2, 3, 2, 4, 2, 0, 4, 6, 2, 339, 3, 24, 2, 24, 2, 30, 2, 24, 2, 30, 2, 24, 2, 30, 2, 24, 2, 30, 2, 24, 2, 7, 1845, 30, 7, 5, 262, 61, 147, 44, 11, 6, 17, 0, 322, 29, 19, 43, 485, 27, 229, 29, 3, 0, 208, 30, 2, 2, 2, 1, 2, 6, 3, 4, 10, 1, 225, 6, 2, 3, 2, 1, 2, 14, 2, 196, 60, 67, 8, 0, 1205, 3, 2, 26, 2, 1, 2, 0, 3, 0, 2, 9, 2, 3, 2, 0, 2, 0, 7, 0, 5, 0, 2, 0, 2, 0, 2, 2, 2, 1, 2, 0, 3, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 1, 2, 0, 3, 3, 2, 6, 2, 3, 2, 3, 2, 0, 2, 9, 2, 16, 6, 2, 2, 4, 2, 16, 4421, 42719, 33, 4381, 3, 5773, 3, 7472, 16, 621, 2467, 541, 1507, 4938, 6, 8489]; + + // This file was generated. Do not modify manually! + var nonASCIIidentifierChars = "\u200c\u200d\xb7\u0300-\u036f\u0387\u0483-\u0487\u0591-\u05bd\u05bf\u05c1\u05c2\u05c4\u05c5\u05c7\u0610-\u061a\u064b-\u0669\u0670\u06d6-\u06dc\u06df-\u06e4\u06e7\u06e8\u06ea-\u06ed\u06f0-\u06f9\u0711\u0730-\u074a\u07a6-\u07b0\u07c0-\u07c9\u07eb-\u07f3\u07fd\u0816-\u0819\u081b-\u0823\u0825-\u0827\u0829-\u082d\u0859-\u085b\u0897-\u089f\u08ca-\u08e1\u08e3-\u0903\u093a-\u093c\u093e-\u094f\u0951-\u0957\u0962\u0963\u0966-\u096f\u0981-\u0983\u09bc\u09be-\u09c4\u09c7\u09c8\u09cb-\u09cd\u09d7\u09e2\u09e3\u09e6-\u09ef\u09fe\u0a01-\u0a03\u0a3c\u0a3e-\u0a42\u0a47\u0a48\u0a4b-\u0a4d\u0a51\u0a66-\u0a71\u0a75\u0a81-\u0a83\u0abc\u0abe-\u0ac5\u0ac7-\u0ac9\u0acb-\u0acd\u0ae2\u0ae3\u0ae6-\u0aef\u0afa-\u0aff\u0b01-\u0b03\u0b3c\u0b3e-\u0b44\u0b47\u0b48\u0b4b-\u0b4d\u0b55-\u0b57\u0b62\u0b63\u0b66-\u0b6f\u0b82\u0bbe-\u0bc2\u0bc6-\u0bc8\u0bca-\u0bcd\u0bd7\u0be6-\u0bef\u0c00-\u0c04\u0c3c\u0c3e-\u0c44\u0c46-\u0c48\u0c4a-\u0c4d\u0c55\u0c56\u0c62\u0c63\u0c66-\u0c6f\u0c81-\u0c83\u0cbc\u0cbe-\u0cc4\u0cc6-\u0cc8\u0cca-\u0ccd\u0cd5\u0cd6\u0ce2\u0ce3\u0ce6-\u0cef\u0cf3\u0d00-\u0d03\u0d3b\u0d3c\u0d3e-\u0d44\u0d46-\u0d48\u0d4a-\u0d4d\u0d57\u0d62\u0d63\u0d66-\u0d6f\u0d81-\u0d83\u0dca\u0dcf-\u0dd4\u0dd6\u0dd8-\u0ddf\u0de6-\u0def\u0df2\u0df3\u0e31\u0e34-\u0e3a\u0e47-\u0e4e\u0e50-\u0e59\u0eb1\u0eb4-\u0ebc\u0ec8-\u0ece\u0ed0-\u0ed9\u0f18\u0f19\u0f20-\u0f29\u0f35\u0f37\u0f39\u0f3e\u0f3f\u0f71-\u0f84\u0f86\u0f87\u0f8d-\u0f97\u0f99-\u0fbc\u0fc6\u102b-\u103e\u1040-\u1049\u1056-\u1059\u105e-\u1060\u1062-\u1064\u1067-\u106d\u1071-\u1074\u1082-\u108d\u108f-\u109d\u135d-\u135f\u1369-\u1371\u1712-\u1715\u1732-\u1734\u1752\u1753\u1772\u1773\u17b4-\u17d3\u17dd\u17e0-\u17e9\u180b-\u180d\u180f-\u1819\u18a9\u1920-\u192b\u1930-\u193b\u1946-\u194f\u19d0-\u19da\u1a17-\u1a1b\u1a55-\u1a5e\u1a60-\u1a7c\u1a7f-\u1a89\u1a90-\u1a99\u1ab0-\u1abd\u1abf-\u1add\u1ae0-\u1aeb\u1b00-\u1b04\u1b34-\u1b44\u1b50-\u1b59\u1b6b-\u1b73\u1b80-\u1b82\u1ba1-\u1bad\u1bb0-\u1bb9\u1be6-\u1bf3\u1c24-\u1c37\u1c40-\u1c49\u1c50-\u1c59\u1cd0-\u1cd2\u1cd4-\u1ce8\u1ced\u1cf4\u1cf7-\u1cf9\u1dc0-\u1dff\u200c\u200d\u203f\u2040\u2054\u20d0-\u20dc\u20e1\u20e5-\u20f0\u2cef-\u2cf1\u2d7f\u2de0-\u2dff\u302a-\u302f\u3099\u309a\u30fb\ua620-\ua629\ua66f\ua674-\ua67d\ua69e\ua69f\ua6f0\ua6f1\ua802\ua806\ua80b\ua823-\ua827\ua82c\ua880\ua881\ua8b4-\ua8c5\ua8d0-\ua8d9\ua8e0-\ua8f1\ua8ff-\ua909\ua926-\ua92d\ua947-\ua953\ua980-\ua983\ua9b3-\ua9c0\ua9d0-\ua9d9\ua9e5\ua9f0-\ua9f9\uaa29-\uaa36\uaa43\uaa4c\uaa4d\uaa50-\uaa59\uaa7b-\uaa7d\uaab0\uaab2-\uaab4\uaab7\uaab8\uaabe\uaabf\uaac1\uaaeb-\uaaef\uaaf5\uaaf6\uabe3-\uabea\uabec\uabed\uabf0-\uabf9\ufb1e\ufe00-\ufe0f\ufe20-\ufe2f\ufe33\ufe34\ufe4d-\ufe4f\uff10-\uff19\uff3f\uff65"; + + // This file was generated. Do not modify manually! + var nonASCIIidentifierStartChars = "\xaa\xb5\xba\xc0-\xd6\xd8-\xf6\xf8-\u02c1\u02c6-\u02d1\u02e0-\u02e4\u02ec\u02ee\u0370-\u0374\u0376\u0377\u037a-\u037d\u037f\u0386\u0388-\u038a\u038c\u038e-\u03a1\u03a3-\u03f5\u03f7-\u0481\u048a-\u052f\u0531-\u0556\u0559\u0560-\u0588\u05d0-\u05ea\u05ef-\u05f2\u0620-\u064a\u066e\u066f\u0671-\u06d3\u06d5\u06e5\u06e6\u06ee\u06ef\u06fa-\u06fc\u06ff\u0710\u0712-\u072f\u074d-\u07a5\u07b1\u07ca-\u07ea\u07f4\u07f5\u07fa\u0800-\u0815\u081a\u0824\u0828\u0840-\u0858\u0860-\u086a\u0870-\u0887\u0889-\u088f\u08a0-\u08c9\u0904-\u0939\u093d\u0950\u0958-\u0961\u0971-\u0980\u0985-\u098c\u098f\u0990\u0993-\u09a8\u09aa-\u09b0\u09b2\u09b6-\u09b9\u09bd\u09ce\u09dc\u09dd\u09df-\u09e1\u09f0\u09f1\u09fc\u0a05-\u0a0a\u0a0f\u0a10\u0a13-\u0a28\u0a2a-\u0a30\u0a32\u0a33\u0a35\u0a36\u0a38\u0a39\u0a59-\u0a5c\u0a5e\u0a72-\u0a74\u0a85-\u0a8d\u0a8f-\u0a91\u0a93-\u0aa8\u0aaa-\u0ab0\u0ab2\u0ab3\u0ab5-\u0ab9\u0abd\u0ad0\u0ae0\u0ae1\u0af9\u0b05-\u0b0c\u0b0f\u0b10\u0b13-\u0b28\u0b2a-\u0b30\u0b32\u0b33\u0b35-\u0b39\u0b3d\u0b5c\u0b5d\u0b5f-\u0b61\u0b71\u0b83\u0b85-\u0b8a\u0b8e-\u0b90\u0b92-\u0b95\u0b99\u0b9a\u0b9c\u0b9e\u0b9f\u0ba3\u0ba4\u0ba8-\u0baa\u0bae-\u0bb9\u0bd0\u0c05-\u0c0c\u0c0e-\u0c10\u0c12-\u0c28\u0c2a-\u0c39\u0c3d\u0c58-\u0c5a\u0c5c\u0c5d\u0c60\u0c61\u0c80\u0c85-\u0c8c\u0c8e-\u0c90\u0c92-\u0ca8\u0caa-\u0cb3\u0cb5-\u0cb9\u0cbd\u0cdc-\u0cde\u0ce0\u0ce1\u0cf1\u0cf2\u0d04-\u0d0c\u0d0e-\u0d10\u0d12-\u0d3a\u0d3d\u0d4e\u0d54-\u0d56\u0d5f-\u0d61\u0d7a-\u0d7f\u0d85-\u0d96\u0d9a-\u0db1\u0db3-\u0dbb\u0dbd\u0dc0-\u0dc6\u0e01-\u0e30\u0e32\u0e33\u0e40-\u0e46\u0e81\u0e82\u0e84\u0e86-\u0e8a\u0e8c-\u0ea3\u0ea5\u0ea7-\u0eb0\u0eb2\u0eb3\u0ebd\u0ec0-\u0ec4\u0ec6\u0edc-\u0edf\u0f00\u0f40-\u0f47\u0f49-\u0f6c\u0f88-\u0f8c\u1000-\u102a\u103f\u1050-\u1055\u105a-\u105d\u1061\u1065\u1066\u106e-\u1070\u1075-\u1081\u108e\u10a0-\u10c5\u10c7\u10cd\u10d0-\u10fa\u10fc-\u1248\u124a-\u124d\u1250-\u1256\u1258\u125a-\u125d\u1260-\u1288\u128a-\u128d\u1290-\u12b0\u12b2-\u12b5\u12b8-\u12be\u12c0\u12c2-\u12c5\u12c8-\u12d6\u12d8-\u1310\u1312-\u1315\u1318-\u135a\u1380-\u138f\u13a0-\u13f5\u13f8-\u13fd\u1401-\u166c\u166f-\u167f\u1681-\u169a\u16a0-\u16ea\u16ee-\u16f8\u1700-\u1711\u171f-\u1731\u1740-\u1751\u1760-\u176c\u176e-\u1770\u1780-\u17b3\u17d7\u17dc\u1820-\u1878\u1880-\u18a8\u18aa\u18b0-\u18f5\u1900-\u191e\u1950-\u196d\u1970-\u1974\u1980-\u19ab\u19b0-\u19c9\u1a00-\u1a16\u1a20-\u1a54\u1aa7\u1b05-\u1b33\u1b45-\u1b4c\u1b83-\u1ba0\u1bae\u1baf\u1bba-\u1be5\u1c00-\u1c23\u1c4d-\u1c4f\u1c5a-\u1c7d\u1c80-\u1c8a\u1c90-\u1cba\u1cbd-\u1cbf\u1ce9-\u1cec\u1cee-\u1cf3\u1cf5\u1cf6\u1cfa\u1d00-\u1dbf\u1e00-\u1f15\u1f18-\u1f1d\u1f20-\u1f45\u1f48-\u1f4d\u1f50-\u1f57\u1f59\u1f5b\u1f5d\u1f5f-\u1f7d\u1f80-\u1fb4\u1fb6-\u1fbc\u1fbe\u1fc2-\u1fc4\u1fc6-\u1fcc\u1fd0-\u1fd3\u1fd6-\u1fdb\u1fe0-\u1fec\u1ff2-\u1ff4\u1ff6-\u1ffc\u2071\u207f\u2090-\u209c\u2102\u2107\u210a-\u2113\u2115\u2118-\u211d\u2124\u2126\u2128\u212a-\u2139\u213c-\u213f\u2145-\u2149\u214e\u2160-\u2188\u2c00-\u2ce4\u2ceb-\u2cee\u2cf2\u2cf3\u2d00-\u2d25\u2d27\u2d2d\u2d30-\u2d67\u2d6f\u2d80-\u2d96\u2da0-\u2da6\u2da8-\u2dae\u2db0-\u2db6\u2db8-\u2dbe\u2dc0-\u2dc6\u2dc8-\u2dce\u2dd0-\u2dd6\u2dd8-\u2dde\u3005-\u3007\u3021-\u3029\u3031-\u3035\u3038-\u303c\u3041-\u3096\u309b-\u309f\u30a1-\u30fa\u30fc-\u30ff\u3105-\u312f\u3131-\u318e\u31a0-\u31bf\u31f0-\u31ff\u3400-\u4dbf\u4e00-\ua48c\ua4d0-\ua4fd\ua500-\ua60c\ua610-\ua61f\ua62a\ua62b\ua640-\ua66e\ua67f-\ua69d\ua6a0-\ua6ef\ua717-\ua71f\ua722-\ua788\ua78b-\ua7dc\ua7f1-\ua801\ua803-\ua805\ua807-\ua80a\ua80c-\ua822\ua840-\ua873\ua882-\ua8b3\ua8f2-\ua8f7\ua8fb\ua8fd\ua8fe\ua90a-\ua925\ua930-\ua946\ua960-\ua97c\ua984-\ua9b2\ua9cf\ua9e0-\ua9e4\ua9e6-\ua9ef\ua9fa-\ua9fe\uaa00-\uaa28\uaa40-\uaa42\uaa44-\uaa4b\uaa60-\uaa76\uaa7a\uaa7e-\uaaaf\uaab1\uaab5\uaab6\uaab9-\uaabd\uaac0\uaac2\uaadb-\uaadd\uaae0-\uaaea\uaaf2-\uaaf4\uab01-\uab06\uab09-\uab0e\uab11-\uab16\uab20-\uab26\uab28-\uab2e\uab30-\uab5a\uab5c-\uab69\uab70-\uabe2\uac00-\ud7a3\ud7b0-\ud7c6\ud7cb-\ud7fb\uf900-\ufa6d\ufa70-\ufad9\ufb00-\ufb06\ufb13-\ufb17\ufb1d\ufb1f-\ufb28\ufb2a-\ufb36\ufb38-\ufb3c\ufb3e\ufb40\ufb41\ufb43\ufb44\ufb46-\ufbb1\ufbd3-\ufd3d\ufd50-\ufd8f\ufd92-\ufdc7\ufdf0-\ufdfb\ufe70-\ufe74\ufe76-\ufefc\uff21-\uff3a\uff41-\uff5a\uff66-\uffbe\uffc2-\uffc7\uffca-\uffcf\uffd2-\uffd7\uffda-\uffdc"; + + // These are a run-length and offset encoded representation of the + // >0xffff code points that are a valid part of identifiers. The + // offset starts at 0x10000, and each pair of numbers represents an + // offset to the next range, and then a size of the range. + + // Reserved word lists for various dialects of the language + + var reservedWords = { + 3: "abstract boolean byte char class double enum export extends final float goto implements import int interface long native package private protected public short static super synchronized throws transient volatile", + 5: "class enum extends super const export import", + 6: "enum", + strict: "implements interface let package private protected public static yield", + strictBind: "eval arguments" + }; + + // And the keywords + + var ecma5AndLessKeywords = "break case catch continue debugger default do else finally for function if return switch throw try var while with null true false instanceof typeof void delete new in this"; + + var keywords$1 = { + 5: ecma5AndLessKeywords, + "5module": ecma5AndLessKeywords + " export import", + 6: ecma5AndLessKeywords + " const class extends export import super" + }; + + var keywordRelationalOperator = /^in(stanceof)?$/; + + // ## Character categories + + var nonASCIIidentifierStart = new RegExp("[" + nonASCIIidentifierStartChars + "]"); + var nonASCIIidentifier = new RegExp("[" + nonASCIIidentifierStartChars + nonASCIIidentifierChars + "]"); + + // This has a complexity linear to the value of the code. The + // assumption is that looking up astral identifier characters is + // rare. + function isInAstralSet(code, set) { + var pos = 0x10000; + for (var i = 0; i < set.length; i += 2) { + pos += set[i]; + if (pos > code) { return false } + pos += set[i + 1]; + if (pos >= code) { return true } + } + return false + } + + // Test whether a given character code starts an identifier. + + function isIdentifierStart(code, astral) { + if (code < 65) { return code === 36 } + if (code < 91) { return true } + if (code < 97) { return code === 95 } + if (code < 123) { return true } + if (code <= 0xffff) { return code >= 0xaa && nonASCIIidentifierStart.test(String.fromCharCode(code)) } + if (astral === false) { return false } + return isInAstralSet(code, astralIdentifierStartCodes) + } + + // Test whether a given character is part of an identifier. + + function isIdentifierChar(code, astral) { + if (code < 48) { return code === 36 } + if (code < 58) { return true } + if (code < 65) { return false } + if (code < 91) { return true } + if (code < 97) { return code === 95 } + if (code < 123) { return true } + if (code <= 0xffff) { return code >= 0xaa && nonASCIIidentifier.test(String.fromCharCode(code)) } + if (astral === false) { return false } + return isInAstralSet(code, astralIdentifierStartCodes) || isInAstralSet(code, astralIdentifierCodes) + } + + // ## Token types + + // The assignment of fine-grained, information-carrying type objects + // allows the tokenizer to store the information it has about a + // token in a way that is very cheap for the parser to look up. + + // All token type variables start with an underscore, to make them + // easy to recognize. + + // The `beforeExpr` property is used to disambiguate between regular + // expressions and divisions. It is set on all token types that can + // be followed by an expression (thus, a slash after them would be a + // regular expression). + // + // The `startsExpr` property is used to check if the token ends a + // `yield` expression. It is set on all token types that either can + // directly start an expression (like a quotation mark) or can + // continue an expression (like the body of a string). + // + // `isLoop` marks a keyword as starting a loop, which is important + // to know when parsing a label, in order to allow or disallow + // continue jumps to that label. + + var TokenType = function TokenType(label, conf) { + if ( conf === void 0 ) conf = {}; + + this.label = label; + this.keyword = conf.keyword; + this.beforeExpr = !!conf.beforeExpr; + this.startsExpr = !!conf.startsExpr; + this.isLoop = !!conf.isLoop; + this.isAssign = !!conf.isAssign; + this.prefix = !!conf.prefix; + this.postfix = !!conf.postfix; + this.binop = conf.binop || null; + this.updateContext = null; + }; + + function binop(name, prec) { + return new TokenType(name, {beforeExpr: true, binop: prec}) + } + var beforeExpr = {beforeExpr: true}, startsExpr = {startsExpr: true}; + + // Map keyword names to token types. + + var keywords = {}; + + // Succinct definitions of keyword token types + function kw(name, options) { + if ( options === void 0 ) options = {}; + + options.keyword = name; + return keywords[name] = new TokenType(name, options) + } + + var types$1 = { + num: new TokenType("num", startsExpr), + regexp: new TokenType("regexp", startsExpr), + string: new TokenType("string", startsExpr), + name: new TokenType("name", startsExpr), + privateId: new TokenType("privateId", startsExpr), + eof: new TokenType("eof"), + + // Punctuation token types. + bracketL: new TokenType("[", {beforeExpr: true, startsExpr: true}), + bracketR: new TokenType("]"), + braceL: new TokenType("{", {beforeExpr: true, startsExpr: true}), + braceR: new TokenType("}"), + parenL: new TokenType("(", {beforeExpr: true, startsExpr: true}), + parenR: new TokenType(")"), + comma: new TokenType(",", beforeExpr), + semi: new TokenType(";", beforeExpr), + colon: new TokenType(":", beforeExpr), + dot: new TokenType("."), + question: new TokenType("?", beforeExpr), + questionDot: new TokenType("?."), + arrow: new TokenType("=>", beforeExpr), + template: new TokenType("template"), + invalidTemplate: new TokenType("invalidTemplate"), + ellipsis: new TokenType("...", beforeExpr), + backQuote: new TokenType("`", startsExpr), + dollarBraceL: new TokenType("${", {beforeExpr: true, startsExpr: true}), + + // Operators. These carry several kinds of properties to help the + // parser use them properly (the presence of these properties is + // what categorizes them as operators). + // + // `binop`, when present, specifies that this operator is a binary + // operator, and will refer to its precedence. + // + // `prefix` and `postfix` mark the operator as a prefix or postfix + // unary operator. + // + // `isAssign` marks all of `=`, `+=`, `-=` etcetera, which act as + // binary operators with a very low precedence, that should result + // in AssignmentExpression nodes. + + eq: new TokenType("=", {beforeExpr: true, isAssign: true}), + assign: new TokenType("_=", {beforeExpr: true, isAssign: true}), + incDec: new TokenType("++/--", {prefix: true, postfix: true, startsExpr: true}), + prefix: new TokenType("!/~", {beforeExpr: true, prefix: true, startsExpr: true}), + logicalOR: binop("||", 1), + logicalAND: binop("&&", 2), + bitwiseOR: binop("|", 3), + bitwiseXOR: binop("^", 4), + bitwiseAND: binop("&", 5), + equality: binop("==/!=/===/!==", 6), + relational: binop("/<=/>=", 7), + bitShift: binop("<>/>>>", 8), + plusMin: new TokenType("+/-", {beforeExpr: true, binop: 9, prefix: true, startsExpr: true}), + modulo: binop("%", 10), + star: binop("*", 10), + slash: binop("/", 10), + starstar: new TokenType("**", {beforeExpr: true}), + coalesce: binop("??", 1), + + // Keyword token types. + _break: kw("break"), + _case: kw("case", beforeExpr), + _catch: kw("catch"), + _continue: kw("continue"), + _debugger: kw("debugger"), + _default: kw("default", beforeExpr), + _do: kw("do", {isLoop: true, beforeExpr: true}), + _else: kw("else", beforeExpr), + _finally: kw("finally"), + _for: kw("for", {isLoop: true}), + _function: kw("function", startsExpr), + _if: kw("if"), + _return: kw("return", beforeExpr), + _switch: kw("switch"), + _throw: kw("throw", beforeExpr), + _try: kw("try"), + _var: kw("var"), + _const: kw("const"), + _while: kw("while", {isLoop: true}), + _with: kw("with"), + _new: kw("new", {beforeExpr: true, startsExpr: true}), + _this: kw("this", startsExpr), + _super: kw("super", startsExpr), + _class: kw("class", startsExpr), + _extends: kw("extends", beforeExpr), + _export: kw("export"), + _import: kw("import", startsExpr), + _null: kw("null", startsExpr), + _true: kw("true", startsExpr), + _false: kw("false", startsExpr), + _in: kw("in", {beforeExpr: true, binop: 7}), + _instanceof: kw("instanceof", {beforeExpr: true, binop: 7}), + _typeof: kw("typeof", {beforeExpr: true, prefix: true, startsExpr: true}), + _void: kw("void", {beforeExpr: true, prefix: true, startsExpr: true}), + _delete: kw("delete", {beforeExpr: true, prefix: true, startsExpr: true}) + }; + + // Matches a whole line break (where CRLF is considered a single + // line break). Used to count lines. + + var lineBreak = /\r\n?|\n|\u2028|\u2029/; + var lineBreakG = new RegExp(lineBreak.source, "g"); + + function isNewLine(code) { + return code === 10 || code === 13 || code === 0x2028 || code === 0x2029 + } + + function nextLineBreak(code, from, end) { + if ( end === void 0 ) end = code.length; + + for (var i = from; i < end; i++) { + var next = code.charCodeAt(i); + if (isNewLine(next)) + { return i < end - 1 && next === 13 && code.charCodeAt(i + 1) === 10 ? i + 2 : i + 1 } + } + return -1 + } + + var nonASCIIwhitespace = /[\u1680\u2000-\u200a\u202f\u205f\u3000\ufeff]/; + + var skipWhiteSpace = /(?:\s|\/\/.*|\/\*[^]*?\*\/)*/g; + + var ref = Object.prototype; + var hasOwnProperty = ref.hasOwnProperty; + var toString = ref.toString; + + var hasOwn = Object.hasOwn || (function (obj, propName) { return ( + hasOwnProperty.call(obj, propName) + ); }); + + var isArray = Array.isArray || (function (obj) { return ( + toString.call(obj) === "[object Array]" + ); }); + + var regexpCache = Object.create(null); + + function wordsRegexp(words) { + return regexpCache[words] || (regexpCache[words] = new RegExp("^(?:" + words.replace(/ /g, "|") + ")$")) + } + + function codePointToString(code) { + // UTF-16 Decoding + if (code <= 0xFFFF) { return String.fromCharCode(code) } + code -= 0x10000; + return String.fromCharCode((code >> 10) + 0xD800, (code & 1023) + 0xDC00) + } + + var loneSurrogate = /(?:[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF])/; + + // These are used when `options.locations` is on, for the + // `startLoc` and `endLoc` properties. + + var Position = function Position(line, col) { + this.line = line; + this.column = col; + }; + + Position.prototype.offset = function offset (n) { + return new Position(this.line, this.column + n) + }; + + var SourceLocation = function SourceLocation(p, start, end) { + this.start = start; + this.end = end; + if (p.sourceFile !== null) { this.source = p.sourceFile; } + }; + + // The `getLineInfo` function is mostly useful when the + // `locations` option is off (for performance reasons) and you + // want to find the line/column position for a given character + // offset. `input` should be the code string that the offset refers + // into. + + function getLineInfo(input, offset) { + for (var line = 1, cur = 0;;) { + var nextBreak = nextLineBreak(input, cur, offset); + if (nextBreak < 0) { return new Position(line, offset - cur) } + ++line; + cur = nextBreak; + } + } + + // A second argument must be given to configure the parser process. + // These options are recognized (only `ecmaVersion` is required): + + var defaultOptions = { + // `ecmaVersion` indicates the ECMAScript version to parse. Must be + // either 3, 5, 6 (or 2015), 7 (2016), 8 (2017), 9 (2018), 10 + // (2019), 11 (2020), 12 (2021), 13 (2022), 14 (2023), or `"latest"` + // (the latest version the library supports). This influences + // support for strict mode, the set of reserved words, and support + // for new syntax features. + ecmaVersion: null, + // `sourceType` indicates the mode the code should be parsed in. + // Can be either `"script"`, `"module"` or `"commonjs"`. This influences global + // strict mode and parsing of `import` and `export` declarations. + sourceType: "script", + // `onInsertedSemicolon` can be a callback that will be called when + // a semicolon is automatically inserted. It will be passed the + // position of the inserted semicolon as an offset, and if + // `locations` is enabled, it is given the location as a `{line, + // column}` object as second argument. + onInsertedSemicolon: null, + // `onTrailingComma` is similar to `onInsertedSemicolon`, but for + // trailing commas. + onTrailingComma: null, + // By default, reserved words are only enforced if ecmaVersion >= 5. + // Set `allowReserved` to a boolean value to explicitly turn this on + // an off. When this option has the value "never", reserved words + // and keywords can also not be used as property names. + allowReserved: null, + // When enabled, a return at the top level is not considered an + // error. + allowReturnOutsideFunction: false, + // When enabled, import/export statements are not constrained to + // appearing at the top of the program, and an import.meta expression + // in a script isn't considered an error. + allowImportExportEverywhere: false, + // By default, await identifiers are allowed to appear at the top-level scope only if ecmaVersion >= 2022. + // When enabled, await identifiers are allowed to appear at the top-level scope, + // but they are still not allowed in non-async functions. + allowAwaitOutsideFunction: null, + // When enabled, super identifiers are not constrained to + // appearing in methods and do not raise an error when they appear elsewhere. + allowSuperOutsideMethod: null, + // When enabled, hashbang directive in the beginning of file is + // allowed and treated as a line comment. Enabled by default when + // `ecmaVersion` >= 2023. + allowHashBang: false, + // By default, the parser will verify that private properties are + // only used in places where they are valid and have been declared. + // Set this to false to turn such checks off. + checkPrivateFields: true, + // When `locations` is on, `loc` properties holding objects with + // `start` and `end` properties in `{line, column}` form (with + // line being 1-based and column 0-based) will be attached to the + // nodes. + locations: false, + // A function can be passed as `onToken` option, which will + // cause Acorn to call that function with object in the same + // format as tokens returned from `tokenizer().getToken()`. Note + // that you are not allowed to call the parser from the + // callback—that will corrupt its internal state. + onToken: null, + // A function can be passed as `onComment` option, which will + // cause Acorn to call that function with `(block, text, start, + // end)` parameters whenever a comment is skipped. `block` is a + // boolean indicating whether this is a block (`/* */`) comment, + // `text` is the content of the comment, and `start` and `end` are + // character offsets that denote the start and end of the comment. + // When the `locations` option is on, two more parameters are + // passed, the full `{line, column}` locations of the start and + // end of the comments. Note that you are not allowed to call the + // parser from the callback—that will corrupt its internal state. + // When this option has an array as value, objects representing the + // comments are pushed to it. + onComment: null, + // Nodes have their start and end characters offsets recorded in + // `start` and `end` properties (directly on the node, rather than + // the `loc` object, which holds line/column data. To also add a + // [semi-standardized][range] `range` property holding a `[start, + // end]` array with the same numbers, set the `ranges` option to + // `true`. + // + // [range]: https://bugzilla.mozilla.org/show_bug.cgi?id=745678 + ranges: false, + // It is possible to parse multiple files into a single AST by + // passing the tree produced by parsing the first file as + // `program` option in subsequent parses. This will add the + // toplevel forms of the parsed file to the `Program` (top) node + // of an existing parse tree. + program: null, + // When `locations` is on, you can pass this to record the source + // file in every node's `loc` object. + sourceFile: null, + // This value, if given, is stored in every node, whether + // `locations` is on or off. + directSourceFile: null, + // When enabled, parenthesized expressions are represented by + // (non-standard) ParenthesizedExpression nodes + preserveParens: false + }; + + // Interpret and default an options object + + var warnedAboutEcmaVersion = false; + + function getOptions(opts) { + var options = {}; + + for (var opt in defaultOptions) + { options[opt] = opts && hasOwn(opts, opt) ? opts[opt] : defaultOptions[opt]; } + + if (options.ecmaVersion === "latest") { + options.ecmaVersion = 1e8; + } else if (options.ecmaVersion == null) { + if (!warnedAboutEcmaVersion && typeof console === "object" && console.warn) { + warnedAboutEcmaVersion = true; + console.warn("Since Acorn 8.0.0, options.ecmaVersion is required.\nDefaulting to 2020, but this will stop working in the future."); + } + options.ecmaVersion = 11; + } else if (options.ecmaVersion >= 2015) { + options.ecmaVersion -= 2009; + } + + if (options.allowReserved == null) + { options.allowReserved = options.ecmaVersion < 5; } + + if (!opts || opts.allowHashBang == null) + { options.allowHashBang = options.ecmaVersion >= 14; } + + if (isArray(options.onToken)) { + var tokens = options.onToken; + options.onToken = function (token) { return tokens.push(token); }; + } + if (isArray(options.onComment)) + { options.onComment = pushComment(options, options.onComment); } + + if (options.sourceType === "commonjs" && options.allowAwaitOutsideFunction) + { throw new Error("Cannot use allowAwaitOutsideFunction with sourceType: commonjs") } + + return options + } + + function pushComment(options, array) { + return function(block, text, start, end, startLoc, endLoc) { + var comment = { + type: block ? "Block" : "Line", + value: text, + start: start, + end: end + }; + if (options.locations) + { comment.loc = new SourceLocation(this, startLoc, endLoc); } + if (options.ranges) + { comment.range = [start, end]; } + array.push(comment); + } + } + + // Each scope gets a bitset that may contain these flags + var + SCOPE_TOP = 1, + SCOPE_FUNCTION = 2, + SCOPE_ASYNC = 4, + SCOPE_GENERATOR = 8, + SCOPE_ARROW = 16, + SCOPE_SIMPLE_CATCH = 32, + SCOPE_SUPER = 64, + SCOPE_DIRECT_SUPER = 128, + SCOPE_CLASS_STATIC_BLOCK = 256, + SCOPE_CLASS_FIELD_INIT = 512, + SCOPE_SWITCH = 1024, + SCOPE_VAR = SCOPE_TOP | SCOPE_FUNCTION | SCOPE_CLASS_STATIC_BLOCK; + + function functionFlags(async, generator) { + return SCOPE_FUNCTION | (async ? SCOPE_ASYNC : 0) | (generator ? SCOPE_GENERATOR : 0) + } + + // Used in checkLVal* and declareName to determine the type of a binding + var + BIND_NONE = 0, // Not a binding + BIND_VAR = 1, // Var-style binding + BIND_LEXICAL = 2, // Let- or const-style binding + BIND_FUNCTION = 3, // Function declaration + BIND_SIMPLE_CATCH = 4, // Simple (identifier pattern) catch binding + BIND_OUTSIDE = 5; // Special case for function names as bound inside the function + + var Parser = function Parser(options, input, startPos) { + this.options = options = getOptions(options); + this.sourceFile = options.sourceFile; + this.keywords = wordsRegexp(keywords$1[options.ecmaVersion >= 6 ? 6 : options.sourceType === "module" ? "5module" : 5]); + var reserved = ""; + if (options.allowReserved !== true) { + reserved = reservedWords[options.ecmaVersion >= 6 ? 6 : options.ecmaVersion === 5 ? 5 : 3]; + if (options.sourceType === "module") { reserved += " await"; } + } + this.reservedWords = wordsRegexp(reserved); + var reservedStrict = (reserved ? reserved + " " : "") + reservedWords.strict; + this.reservedWordsStrict = wordsRegexp(reservedStrict); + this.reservedWordsStrictBind = wordsRegexp(reservedStrict + " " + reservedWords.strictBind); + this.input = String(input); + + // Used to signal to callers of `readWord1` whether the word + // contained any escape sequences. This is needed because words with + // escape sequences must not be interpreted as keywords. + this.containsEsc = false; + + // Set up token state + + // The current position of the tokenizer in the input. + if (startPos) { + this.pos = startPos; + this.lineStart = this.input.lastIndexOf("\n", startPos - 1) + 1; + this.curLine = this.input.slice(0, this.lineStart).split(lineBreak).length; + } else { + this.pos = this.lineStart = 0; + this.curLine = 1; + } + + // Properties of the current token: + // Its type + this.type = types$1.eof; + // For tokens that include more information than their type, the value + this.value = null; + // Its start and end offset + this.start = this.end = this.pos; + // And, if locations are used, the {line, column} object + // corresponding to those offsets + this.startLoc = this.endLoc = this.curPosition(); + + // Position information for the previous token + this.lastTokEndLoc = this.lastTokStartLoc = null; + this.lastTokStart = this.lastTokEnd = this.pos; + + // The context stack is used to superficially track syntactic + // context to predict whether a regular expression is allowed in a + // given position. + this.context = this.initialContext(); + this.exprAllowed = true; + + // Figure out if it's a module code. + this.inModule = options.sourceType === "module"; + this.strict = this.inModule || this.strictDirective(this.pos); + + // Used to signify the start of a potential arrow function + this.potentialArrowAt = -1; + this.potentialArrowInForAwait = false; + + // Positions to delayed-check that yield/await does not exist in default parameters. + this.yieldPos = this.awaitPos = this.awaitIdentPos = 0; + // Labels in scope. + this.labels = []; + // Thus-far undefined exports. + this.undefinedExports = Object.create(null); + + // If enabled, skip leading hashbang line. + if (this.pos === 0 && options.allowHashBang && this.input.slice(0, 2) === "#!") + { this.skipLineComment(2); } + + // Scope tracking for duplicate variable names (see scope.js) + this.scopeStack = []; + this.enterScope( + this.options.sourceType === "commonjs" + // In commonjs, the top-level scope behaves like a function scope + ? SCOPE_FUNCTION + : SCOPE_TOP + ); + + // For RegExp validation + this.regexpState = null; + + // The stack of private names. + // Each element has two properties: 'declared' and 'used'. + // When it exited from the outermost class definition, all used private names must be declared. + this.privateNameStack = []; + }; + + var prototypeAccessors = { inFunction: { configurable: true },inGenerator: { configurable: true },inAsync: { configurable: true },canAwait: { configurable: true },allowReturn: { configurable: true },allowSuper: { configurable: true },allowDirectSuper: { configurable: true },treatFunctionsAsVar: { configurable: true },allowNewDotTarget: { configurable: true },allowUsing: { configurable: true },inClassStaticBlock: { configurable: true } }; + + Parser.prototype.parse = function parse () { + var node = this.options.program || this.startNode(); + this.nextToken(); + return this.parseTopLevel(node) + }; + + prototypeAccessors.inFunction.get = function () { return (this.currentVarScope().flags & SCOPE_FUNCTION) > 0 }; + + prototypeAccessors.inGenerator.get = function () { return (this.currentVarScope().flags & SCOPE_GENERATOR) > 0 }; + + prototypeAccessors.inAsync.get = function () { return (this.currentVarScope().flags & SCOPE_ASYNC) > 0 }; + + prototypeAccessors.canAwait.get = function () { + for (var i = this.scopeStack.length - 1; i >= 0; i--) { + var ref = this.scopeStack[i]; + var flags = ref.flags; + if (flags & (SCOPE_CLASS_STATIC_BLOCK | SCOPE_CLASS_FIELD_INIT)) { return false } + if (flags & SCOPE_FUNCTION) { return (flags & SCOPE_ASYNC) > 0 } + } + return (this.inModule && this.options.ecmaVersion >= 13) || this.options.allowAwaitOutsideFunction + }; + + prototypeAccessors.allowReturn.get = function () { + if (this.inFunction) { return true } + if (this.options.allowReturnOutsideFunction && this.currentVarScope().flags & SCOPE_TOP) { return true } + return false + }; + + prototypeAccessors.allowSuper.get = function () { + var ref = this.currentThisScope(); + var flags = ref.flags; + return (flags & SCOPE_SUPER) > 0 || this.options.allowSuperOutsideMethod + }; + + prototypeAccessors.allowDirectSuper.get = function () { return (this.currentThisScope().flags & SCOPE_DIRECT_SUPER) > 0 }; + + prototypeAccessors.treatFunctionsAsVar.get = function () { return this.treatFunctionsAsVarInScope(this.currentScope()) }; + + prototypeAccessors.allowNewDotTarget.get = function () { + for (var i = this.scopeStack.length - 1; i >= 0; i--) { + var ref = this.scopeStack[i]; + var flags = ref.flags; + if (flags & (SCOPE_CLASS_STATIC_BLOCK | SCOPE_CLASS_FIELD_INIT) || + ((flags & SCOPE_FUNCTION) && !(flags & SCOPE_ARROW))) { return true } + } + return false + }; + + prototypeAccessors.allowUsing.get = function () { + var ref = this.currentScope(); + var flags = ref.flags; + if (flags & SCOPE_SWITCH) { return false } + if (!this.inModule && flags & SCOPE_TOP) { return false } + return true + }; + + prototypeAccessors.inClassStaticBlock.get = function () { + return (this.currentVarScope().flags & SCOPE_CLASS_STATIC_BLOCK) > 0 + }; + + Parser.extend = function extend () { + var plugins = [], len = arguments.length; + while ( len-- ) plugins[ len ] = arguments[ len ]; + + var cls = this; + for (var i = 0; i < plugins.length; i++) { cls = plugins[i](cls); } + return cls + }; + + Parser.parse = function parse (input, options) { + return new this(options, input).parse() + }; + + Parser.parseExpressionAt = function parseExpressionAt (input, pos, options) { + var parser = new this(options, input, pos); + parser.nextToken(); + return parser.parseExpression() + }; + + Parser.tokenizer = function tokenizer (input, options) { + return new this(options, input) + }; + + Object.defineProperties( Parser.prototype, prototypeAccessors ); + + var pp$9 = Parser.prototype; + + // ## Parser utilities + + var literal = /^(?:'((?:\\[^]|[^'\\])*?)'|"((?:\\[^]|[^"\\])*?)")/; + pp$9.strictDirective = function(start) { + if (this.options.ecmaVersion < 5) { return false } + for (;;) { + // Try to find string literal. + skipWhiteSpace.lastIndex = start; + start += skipWhiteSpace.exec(this.input)[0].length; + var match = literal.exec(this.input.slice(start)); + if (!match) { return false } + if ((match[1] || match[2]) === "use strict") { + skipWhiteSpace.lastIndex = start + match[0].length; + var spaceAfter = skipWhiteSpace.exec(this.input), end = spaceAfter.index + spaceAfter[0].length; + var next = this.input.charAt(end); + return next === ";" || next === "}" || + (lineBreak.test(spaceAfter[0]) && + !(/[(`.[+\-/*%<>=,?^&]/.test(next) || next === "!" && this.input.charAt(end + 1) === "=")) + } + start += match[0].length; + + // Skip semicolon, if any. + skipWhiteSpace.lastIndex = start; + start += skipWhiteSpace.exec(this.input)[0].length; + if (this.input[start] === ";") + { start++; } + } + }; + + // Predicate that tests whether the next token is of the given + // type, and if yes, consumes it as a side effect. + + pp$9.eat = function(type) { + if (this.type === type) { + this.next(); + return true + } else { + return false + } + }; + + // Tests whether parsed token is a contextual keyword. + + pp$9.isContextual = function(name) { + return this.type === types$1.name && this.value === name && !this.containsEsc + }; + + // Consumes contextual keyword if possible. + + pp$9.eatContextual = function(name) { + if (!this.isContextual(name)) { return false } + this.next(); + return true + }; + + // Asserts that following token is given contextual keyword. + + pp$9.expectContextual = function(name) { + if (!this.eatContextual(name)) { this.unexpected(); } + }; + + // Test whether a semicolon can be inserted at the current position. + + pp$9.canInsertSemicolon = function() { + return this.type === types$1.eof || + this.type === types$1.braceR || + lineBreak.test(this.input.slice(this.lastTokEnd, this.start)) + }; + + pp$9.insertSemicolon = function() { + if (this.canInsertSemicolon()) { + if (this.options.onInsertedSemicolon) + { this.options.onInsertedSemicolon(this.lastTokEnd, this.lastTokEndLoc); } + return true + } + }; + + // Consume a semicolon, or, failing that, see if we are allowed to + // pretend that there is a semicolon at this position. + + pp$9.semicolon = function() { + if (!this.eat(types$1.semi) && !this.insertSemicolon()) { this.unexpected(); } + }; + + pp$9.afterTrailingComma = function(tokType, notNext) { + if (this.type === tokType) { + if (this.options.onTrailingComma) + { this.options.onTrailingComma(this.lastTokStart, this.lastTokStartLoc); } + if (!notNext) + { this.next(); } + return true + } + }; + + // Expect a token of a given type. If found, consume it, otherwise, + // raise an unexpected token error. + + pp$9.expect = function(type) { + this.eat(type) || this.unexpected(); + }; + + // Raise an unexpected token error. + + pp$9.unexpected = function(pos) { + this.raise(pos != null ? pos : this.start, "Unexpected token"); + }; + + var DestructuringErrors = function DestructuringErrors() { + this.shorthandAssign = + this.trailingComma = + this.parenthesizedAssign = + this.parenthesizedBind = + this.doubleProto = + -1; + }; + + pp$9.checkPatternErrors = function(refDestructuringErrors, isAssign) { + if (!refDestructuringErrors) { return } + if (refDestructuringErrors.trailingComma > -1) + { this.raiseRecoverable(refDestructuringErrors.trailingComma, "Comma is not permitted after the rest element"); } + var parens = isAssign ? refDestructuringErrors.parenthesizedAssign : refDestructuringErrors.parenthesizedBind; + if (parens > -1) { this.raiseRecoverable(parens, isAssign ? "Assigning to rvalue" : "Parenthesized pattern"); } + }; + + pp$9.checkExpressionErrors = function(refDestructuringErrors, andThrow) { + if (!refDestructuringErrors) { return false } + var shorthandAssign = refDestructuringErrors.shorthandAssign; + var doubleProto = refDestructuringErrors.doubleProto; + if (!andThrow) { return shorthandAssign >= 0 || doubleProto >= 0 } + if (shorthandAssign >= 0) + { this.raise(shorthandAssign, "Shorthand property assignments are valid only in destructuring patterns"); } + if (doubleProto >= 0) + { this.raiseRecoverable(doubleProto, "Redefinition of __proto__ property"); } + }; + + pp$9.checkYieldAwaitInDefaultParams = function() { + if (this.yieldPos && (!this.awaitPos || this.yieldPos < this.awaitPos)) + { this.raise(this.yieldPos, "Yield expression cannot be a default value"); } + if (this.awaitPos) + { this.raise(this.awaitPos, "Await expression cannot be a default value"); } + }; + + pp$9.isSimpleAssignTarget = function(expr) { + if (expr.type === "ParenthesizedExpression") + { return this.isSimpleAssignTarget(expr.expression) } + return expr.type === "Identifier" || expr.type === "MemberExpression" + }; + + var pp$8 = Parser.prototype; + + // ### Statement parsing + + // Parse a program. Initializes the parser, reads any number of + // statements, and wraps them in a Program node. Optionally takes a + // `program` argument. If present, the statements will be appended + // to its body instead of creating a new node. + + pp$8.parseTopLevel = function(node) { + var exports = Object.create(null); + if (!node.body) { node.body = []; } + while (this.type !== types$1.eof) { + var stmt = this.parseStatement(null, true, exports); + node.body.push(stmt); + } + if (this.inModule) + { for (var i = 0, list = Object.keys(this.undefinedExports); i < list.length; i += 1) + { + var name = list[i]; + + this.raiseRecoverable(this.undefinedExports[name].start, ("Export '" + name + "' is not defined")); + } } + this.adaptDirectivePrologue(node.body); + this.next(); + node.sourceType = this.options.sourceType === "commonjs" ? "script" : this.options.sourceType; + return this.finishNode(node, "Program") + }; + + var loopLabel = {kind: "loop"}, switchLabel = {kind: "switch"}; + + pp$8.isLet = function(context) { + if (this.options.ecmaVersion < 6 || !this.isContextual("let")) { return false } + skipWhiteSpace.lastIndex = this.pos; + var skip = skipWhiteSpace.exec(this.input); + var next = this.pos + skip[0].length, nextCh = this.fullCharCodeAt(next); + // For ambiguous cases, determine if a LexicalDeclaration (or only a + // Statement) is allowed here. If context is not empty then only a Statement + // is allowed. However, `let [` is an explicit negative lookahead for + // ExpressionStatement, so special-case it first. + if (nextCh === 91 || nextCh === 92) { return true } // '[', '\' + if (context) { return false } + + if (nextCh === 123) { return true } // '{' + if (isIdentifierStart(nextCh)) { + var start = next; + do { next += nextCh <= 0xffff ? 1 : 2; } + while (isIdentifierChar(nextCh = this.fullCharCodeAt(next))) + if (nextCh === 92) { return true } + var ident = this.input.slice(start, next); + if (!keywordRelationalOperator.test(ident)) { return true } + } + return false + }; + + // check 'async [no LineTerminator here] function' + // - 'async /*foo*/ function' is OK. + // - 'async /*\n*/ function' is invalid. + pp$8.isAsyncFunction = function() { + if (this.options.ecmaVersion < 8 || !this.isContextual("async")) + { return false } + + skipWhiteSpace.lastIndex = this.pos; + var skip = skipWhiteSpace.exec(this.input); + var next = this.pos + skip[0].length, after; + return !lineBreak.test(this.input.slice(this.pos, next)) && + this.input.slice(next, next + 8) === "function" && + (next + 8 === this.input.length || + !(isIdentifierChar(after = this.fullCharCodeAt(next + 8)) || after === 92 /* '\' */)) + }; + + pp$8.isUsingKeyword = function(isAwaitUsing, isFor) { + if (this.options.ecmaVersion < 17 || !this.isContextual(isAwaitUsing ? "await" : "using")) + { return false } + + skipWhiteSpace.lastIndex = this.pos; + var skip = skipWhiteSpace.exec(this.input); + var next = this.pos + skip[0].length; + + if (lineBreak.test(this.input.slice(this.pos, next))) { return false } + + if (isAwaitUsing) { + var usingEndPos = next + 5 /* using */, after; + if (this.input.slice(next, usingEndPos) !== "using" || + usingEndPos === this.input.length || + isIdentifierChar(after = this.fullCharCodeAt(usingEndPos)) || + after === 92 /* '\' */ + ) { return false } + + skipWhiteSpace.lastIndex = usingEndPos; + var skipAfterUsing = skipWhiteSpace.exec(this.input); + next = usingEndPos + skipAfterUsing[0].length; + if (skipAfterUsing && lineBreak.test(this.input.slice(usingEndPos, next))) { return false } + } + + var ch = this.fullCharCodeAt(next); + if (!isIdentifierStart(ch) && ch !== 92 /* '\' */) { return false } + var idStart = next; + do { next += ch <= 0xffff ? 1 : 2; } + while (isIdentifierChar(ch = this.fullCharCodeAt(next))) + if (ch === 92) { return true } + var id = this.input.slice(idStart, next); + if (keywordRelationalOperator.test(id) || isFor && id === "of") { return false } + return true + }; + + pp$8.isAwaitUsing = function(isFor) { + return this.isUsingKeyword(true, isFor) + }; + + pp$8.isUsing = function(isFor) { + return this.isUsingKeyword(false, isFor) + }; + + // Parse a single statement. + // + // If expecting a statement and finding a slash operator, parse a + // regular expression literal. This is to handle cases like + // `if (foo) /blah/.exec(foo)`, where looking at the previous token + // does not help. + + pp$8.parseStatement = function(context, topLevel, exports) { + var starttype = this.type, node = this.startNode(), kind; + + if (this.isLet(context)) { + starttype = types$1._var; + kind = "let"; + } + + // Most types of statements are recognized by the keyword they + // start with. Many are trivial to parse, some require a bit of + // complexity. + + switch (starttype) { + case types$1._break: case types$1._continue: return this.parseBreakContinueStatement(node, starttype.keyword) + case types$1._debugger: return this.parseDebuggerStatement(node) + case types$1._do: return this.parseDoStatement(node) + case types$1._for: return this.parseForStatement(node) + case types$1._function: + // Function as sole body of either an if statement or a labeled statement + // works, but not when it is part of a labeled statement that is the sole + // body of an if statement. + if ((context && (this.strict || context !== "if" && context !== "label")) && this.options.ecmaVersion >= 6) { this.unexpected(); } + return this.parseFunctionStatement(node, false, !context) + case types$1._class: + if (context) { this.unexpected(); } + return this.parseClass(node, true) + case types$1._if: return this.parseIfStatement(node) + case types$1._return: return this.parseReturnStatement(node) + case types$1._switch: return this.parseSwitchStatement(node) + case types$1._throw: return this.parseThrowStatement(node) + case types$1._try: return this.parseTryStatement(node) + case types$1._const: case types$1._var: + kind = kind || this.value; + if (context && kind !== "var") { this.unexpected(); } + return this.parseVarStatement(node, kind) + case types$1._while: return this.parseWhileStatement(node) + case types$1._with: return this.parseWithStatement(node) + case types$1.braceL: return this.parseBlock(true, node) + case types$1.semi: return this.parseEmptyStatement(node) + case types$1._export: + case types$1._import: + if (this.options.ecmaVersion > 10 && starttype === types$1._import) { + skipWhiteSpace.lastIndex = this.pos; + var skip = skipWhiteSpace.exec(this.input); + var next = this.pos + skip[0].length, nextCh = this.input.charCodeAt(next); + if (nextCh === 40 || nextCh === 46) // '(' or '.' + { return this.parseExpressionStatement(node, this.parseExpression()) } + } + + if (!this.options.allowImportExportEverywhere) { + if (!topLevel) + { this.raise(this.start, "'import' and 'export' may only appear at the top level"); } + if (!this.inModule) + { this.raise(this.start, "'import' and 'export' may appear only with 'sourceType: module'"); } + } + return starttype === types$1._import ? this.parseImport(node) : this.parseExport(node, exports) + + // If the statement does not start with a statement keyword or a + // brace, it's an ExpressionStatement or LabeledStatement. We + // simply start parsing an expression, and afterwards, if the + // next token is a colon and the expression was a simple + // Identifier node, we switch to interpreting it as a label. + default: + if (this.isAsyncFunction()) { + if (context) { this.unexpected(); } + this.next(); + return this.parseFunctionStatement(node, true, !context) + } + + var usingKind = this.isAwaitUsing(false) ? "await using" : this.isUsing(false) ? "using" : null; + if (usingKind) { + if (!this.allowUsing) { + this.raise(this.start, "Using declaration cannot appear in the top level when source type is `script` or in the bare case statement"); + } + if (usingKind === "await using") { + if (!this.canAwait) { + this.raise(this.start, "Await using cannot appear outside of async function"); + } + this.next(); + } + this.next(); + this.parseVar(node, false, usingKind); + this.semicolon(); + return this.finishNode(node, "VariableDeclaration") + } + + var maybeName = this.value, expr = this.parseExpression(); + if (starttype === types$1.name && expr.type === "Identifier" && this.eat(types$1.colon)) + { return this.parseLabeledStatement(node, maybeName, expr, context) } + else { return this.parseExpressionStatement(node, expr) } + } + }; + + pp$8.parseBreakContinueStatement = function(node, keyword) { + var isBreak = keyword === "break"; + this.next(); + if (this.eat(types$1.semi) || this.insertSemicolon()) { node.label = null; } + else if (this.type !== types$1.name) { this.unexpected(); } + else { + node.label = this.parseIdent(); + this.semicolon(); + } + + // Verify that there is an actual destination to break or + // continue to. + var i = 0; + for (; i < this.labels.length; ++i) { + var lab = this.labels[i]; + if (node.label == null || lab.name === node.label.name) { + if (lab.kind != null && (isBreak || lab.kind === "loop")) { break } + if (node.label && isBreak) { break } + } + } + if (i === this.labels.length) { this.raise(node.start, "Unsyntactic " + keyword); } + return this.finishNode(node, isBreak ? "BreakStatement" : "ContinueStatement") + }; + + pp$8.parseDebuggerStatement = function(node) { + this.next(); + this.semicolon(); + return this.finishNode(node, "DebuggerStatement") + }; + + pp$8.parseDoStatement = function(node) { + this.next(); + this.labels.push(loopLabel); + node.body = this.parseStatement("do"); + this.labels.pop(); + this.expect(types$1._while); + node.test = this.parseParenExpression(); + if (this.options.ecmaVersion >= 6) + { this.eat(types$1.semi); } + else + { this.semicolon(); } + return this.finishNode(node, "DoWhileStatement") + }; + + // Disambiguating between a `for` and a `for`/`in` or `for`/`of` + // loop is non-trivial. Basically, we have to parse the init `var` + // statement or expression, disallowing the `in` operator (see + // the second parameter to `parseExpression`), and then check + // whether the next token is `in` or `of`. When there is no init + // part (semicolon immediately after the opening parenthesis), it + // is a regular `for` loop. + + pp$8.parseForStatement = function(node) { + this.next(); + var awaitAt = (this.options.ecmaVersion >= 9 && this.canAwait && this.eatContextual("await")) ? this.lastTokStart : -1; + this.labels.push(loopLabel); + this.enterScope(0); + this.expect(types$1.parenL); + if (this.type === types$1.semi) { + if (awaitAt > -1) { this.unexpected(awaitAt); } + return this.parseFor(node, null) + } + var isLet = this.isLet(); + if (this.type === types$1._var || this.type === types$1._const || isLet) { + var init$1 = this.startNode(), kind = isLet ? "let" : this.value; + this.next(); + this.parseVar(init$1, true, kind); + this.finishNode(init$1, "VariableDeclaration"); + return this.parseForAfterInit(node, init$1, awaitAt) + } + var startsWithLet = this.isContextual("let"), isForOf = false; + + var usingKind = this.isUsing(true) ? "using" : this.isAwaitUsing(true) ? "await using" : null; + if (usingKind) { + var init$2 = this.startNode(); + this.next(); + if (usingKind === "await using") { + if (!this.canAwait) { + this.raise(this.start, "Await using cannot appear outside of async function"); + } + this.next(); + } + this.parseVar(init$2, true, usingKind); + this.finishNode(init$2, "VariableDeclaration"); + return this.parseForAfterInit(node, init$2, awaitAt) + } + var containsEsc = this.containsEsc; + var refDestructuringErrors = new DestructuringErrors; + var initPos = this.start; + var init = awaitAt > -1 + ? this.parseExprSubscripts(refDestructuringErrors, "await") + : this.parseExpression(true, refDestructuringErrors); + if (this.type === types$1._in || (isForOf = this.options.ecmaVersion >= 6 && this.isContextual("of"))) { + if (awaitAt > -1) { // implies `ecmaVersion >= 9` (see declaration of awaitAt) + if (this.type === types$1._in) { this.unexpected(awaitAt); } + node.await = true; + } else if (isForOf && this.options.ecmaVersion >= 8) { + if (init.start === initPos && !containsEsc && init.type === "Identifier" && init.name === "async") { this.unexpected(); } + else if (this.options.ecmaVersion >= 9) { node.await = false; } + } + if (startsWithLet && isForOf) { this.raise(init.start, "The left-hand side of a for-of loop may not start with 'let'."); } + this.toAssignable(init, false, refDestructuringErrors); + this.checkLValPattern(init); + return this.parseForIn(node, init) + } else { + this.checkExpressionErrors(refDestructuringErrors, true); + } + if (awaitAt > -1) { this.unexpected(awaitAt); } + return this.parseFor(node, init) + }; + + // Helper method to parse for loop after variable initialization + pp$8.parseForAfterInit = function(node, init, awaitAt) { + if ((this.type === types$1._in || (this.options.ecmaVersion >= 6 && this.isContextual("of"))) && init.declarations.length === 1) { + if (this.options.ecmaVersion >= 9) { + if (this.type === types$1._in) { + if (awaitAt > -1) { this.unexpected(awaitAt); } + } else { node.await = awaitAt > -1; } + } + return this.parseForIn(node, init) + } + if (awaitAt > -1) { this.unexpected(awaitAt); } + return this.parseFor(node, init) + }; + + pp$8.parseFunctionStatement = function(node, isAsync, declarationPosition) { + this.next(); + return this.parseFunction(node, FUNC_STATEMENT | (declarationPosition ? 0 : FUNC_HANGING_STATEMENT), false, isAsync) + }; + + pp$8.parseIfStatement = function(node) { + this.next(); + node.test = this.parseParenExpression(); + // allow function declarations in branches, but only in non-strict mode + node.consequent = this.parseStatement("if"); + node.alternate = this.eat(types$1._else) ? this.parseStatement("if") : null; + return this.finishNode(node, "IfStatement") + }; + + pp$8.parseReturnStatement = function(node) { + if (!this.allowReturn) + { this.raise(this.start, "'return' outside of function"); } + this.next(); + + // In `return` (and `break`/`continue`), the keywords with + // optional arguments, we eagerly look for a semicolon or the + // possibility to insert one. + + if (this.eat(types$1.semi) || this.insertSemicolon()) { node.argument = null; } + else { node.argument = this.parseExpression(); this.semicolon(); } + return this.finishNode(node, "ReturnStatement") + }; + + pp$8.parseSwitchStatement = function(node) { + this.next(); + node.discriminant = this.parseParenExpression(); + node.cases = []; + this.expect(types$1.braceL); + this.labels.push(switchLabel); + this.enterScope(SCOPE_SWITCH); + + // Statements under must be grouped (by label) in SwitchCase + // nodes. `cur` is used to keep the node that we are currently + // adding statements to. + + var cur; + for (var sawDefault = false; this.type !== types$1.braceR;) { + if (this.type === types$1._case || this.type === types$1._default) { + var isCase = this.type === types$1._case; + if (cur) { this.finishNode(cur, "SwitchCase"); } + node.cases.push(cur = this.startNode()); + cur.consequent = []; + this.next(); + if (isCase) { + cur.test = this.parseExpression(); + } else { + if (sawDefault) { this.raiseRecoverable(this.lastTokStart, "Multiple default clauses"); } + sawDefault = true; + cur.test = null; + } + this.expect(types$1.colon); + } else { + if (!cur) { this.unexpected(); } + cur.consequent.push(this.parseStatement(null)); + } + } + this.exitScope(); + if (cur) { this.finishNode(cur, "SwitchCase"); } + this.next(); // Closing brace + this.labels.pop(); + return this.finishNode(node, "SwitchStatement") + }; + + pp$8.parseThrowStatement = function(node) { + this.next(); + if (lineBreak.test(this.input.slice(this.lastTokEnd, this.start))) + { this.raise(this.lastTokEnd, "Illegal newline after throw"); } + node.argument = this.parseExpression(); + this.semicolon(); + return this.finishNode(node, "ThrowStatement") + }; + + // Reused empty array added for node fields that are always empty. + + var empty$1 = []; + + pp$8.parseCatchClauseParam = function() { + var param = this.parseBindingAtom(); + var simple = param.type === "Identifier"; + this.enterScope(simple ? SCOPE_SIMPLE_CATCH : 0); + this.checkLValPattern(param, simple ? BIND_SIMPLE_CATCH : BIND_LEXICAL); + this.expect(types$1.parenR); + + return param + }; + + pp$8.parseTryStatement = function(node) { + this.next(); + node.block = this.parseBlock(); + node.handler = null; + if (this.type === types$1._catch) { + var clause = this.startNode(); + this.next(); + if (this.eat(types$1.parenL)) { + clause.param = this.parseCatchClauseParam(); + } else { + if (this.options.ecmaVersion < 10) { this.unexpected(); } + clause.param = null; + this.enterScope(0); + } + clause.body = this.parseBlock(false); + this.exitScope(); + node.handler = this.finishNode(clause, "CatchClause"); + } + node.finalizer = this.eat(types$1._finally) ? this.parseBlock() : null; + if (!node.handler && !node.finalizer) + { this.raise(node.start, "Missing catch or finally clause"); } + return this.finishNode(node, "TryStatement") + }; + + pp$8.parseVarStatement = function(node, kind, allowMissingInitializer) { + this.next(); + this.parseVar(node, false, kind, allowMissingInitializer); + this.semicolon(); + return this.finishNode(node, "VariableDeclaration") + }; + + pp$8.parseWhileStatement = function(node) { + this.next(); + node.test = this.parseParenExpression(); + this.labels.push(loopLabel); + node.body = this.parseStatement("while"); + this.labels.pop(); + return this.finishNode(node, "WhileStatement") + }; + + pp$8.parseWithStatement = function(node) { + if (this.strict) { this.raise(this.start, "'with' in strict mode"); } + this.next(); + node.object = this.parseParenExpression(); + node.body = this.parseStatement("with"); + return this.finishNode(node, "WithStatement") + }; + + pp$8.parseEmptyStatement = function(node) { + this.next(); + return this.finishNode(node, "EmptyStatement") + }; + + pp$8.parseLabeledStatement = function(node, maybeName, expr, context) { + for (var i$1 = 0, list = this.labels; i$1 < list.length; i$1 += 1) + { + var label = list[i$1]; + + if (label.name === maybeName) + { this.raise(expr.start, "Label '" + maybeName + "' is already declared"); + } } + var kind = this.type.isLoop ? "loop" : this.type === types$1._switch ? "switch" : null; + for (var i = this.labels.length - 1; i >= 0; i--) { + var label$1 = this.labels[i]; + if (label$1.statementStart === node.start) { + // Update information about previous labels on this node + label$1.statementStart = this.start; + label$1.kind = kind; + } else { break } + } + this.labels.push({name: maybeName, kind: kind, statementStart: this.start}); + node.body = this.parseStatement(context ? context.indexOf("label") === -1 ? context + "label" : context : "label"); + this.labels.pop(); + node.label = expr; + return this.finishNode(node, "LabeledStatement") + }; + + pp$8.parseExpressionStatement = function(node, expr) { + node.expression = expr; + this.semicolon(); + return this.finishNode(node, "ExpressionStatement") + }; + + // Parse a semicolon-enclosed block of statements, handling `"use + // strict"` declarations when `allowStrict` is true (used for + // function bodies). + + pp$8.parseBlock = function(createNewLexicalScope, node, exitStrict) { + if ( createNewLexicalScope === void 0 ) createNewLexicalScope = true; + if ( node === void 0 ) node = this.startNode(); + + node.body = []; + this.expect(types$1.braceL); + if (createNewLexicalScope) { this.enterScope(0); } + while (this.type !== types$1.braceR) { + var stmt = this.parseStatement(null); + node.body.push(stmt); + } + if (exitStrict) { this.strict = false; } + this.next(); + if (createNewLexicalScope) { this.exitScope(); } + return this.finishNode(node, "BlockStatement") + }; + + // Parse a regular `for` loop. The disambiguation code in + // `parseStatement` will already have parsed the init statement or + // expression. + + pp$8.parseFor = function(node, init) { + node.init = init; + this.expect(types$1.semi); + node.test = this.type === types$1.semi ? null : this.parseExpression(); + this.expect(types$1.semi); + node.update = this.type === types$1.parenR ? null : this.parseExpression(); + this.expect(types$1.parenR); + node.body = this.parseStatement("for"); + this.exitScope(); + this.labels.pop(); + return this.finishNode(node, "ForStatement") + }; + + // Parse a `for`/`in` and `for`/`of` loop, which are almost + // same from parser's perspective. + + pp$8.parseForIn = function(node, init) { + var isForIn = this.type === types$1._in; + this.next(); + + if ( + init.type === "VariableDeclaration" && + init.declarations[0].init != null && + ( + !isForIn || + this.options.ecmaVersion < 8 || + this.strict || + init.kind !== "var" || + init.declarations[0].id.type !== "Identifier" + ) + ) { + this.raise( + init.start, + ((isForIn ? "for-in" : "for-of") + " loop variable declaration may not have an initializer") + ); + } + node.left = init; + node.right = isForIn ? this.parseExpression() : this.parseMaybeAssign(); + this.expect(types$1.parenR); + node.body = this.parseStatement("for"); + this.exitScope(); + this.labels.pop(); + return this.finishNode(node, isForIn ? "ForInStatement" : "ForOfStatement") + }; + + // Parse a list of variable declarations. + + pp$8.parseVar = function(node, isFor, kind, allowMissingInitializer) { + node.declarations = []; + node.kind = kind; + for (;;) { + var decl = this.startNode(); + this.parseVarId(decl, kind); + if (this.eat(types$1.eq)) { + decl.init = this.parseMaybeAssign(isFor); + } else if (!allowMissingInitializer && kind === "const" && !(this.type === types$1._in || (this.options.ecmaVersion >= 6 && this.isContextual("of")))) { + this.unexpected(); + } else if (!allowMissingInitializer && (kind === "using" || kind === "await using") && this.options.ecmaVersion >= 17 && this.type !== types$1._in && !this.isContextual("of")) { + this.raise(this.lastTokEnd, ("Missing initializer in " + kind + " declaration")); + } else if (!allowMissingInitializer && decl.id.type !== "Identifier" && !(isFor && (this.type === types$1._in || this.isContextual("of")))) { + this.raise(this.lastTokEnd, "Complex binding patterns require an initialization value"); + } else { + decl.init = null; + } + node.declarations.push(this.finishNode(decl, "VariableDeclarator")); + if (!this.eat(types$1.comma)) { break } + } + return node + }; + + pp$8.parseVarId = function(decl, kind) { + decl.id = kind === "using" || kind === "await using" + ? this.parseIdent() + : this.parseBindingAtom(); + + this.checkLValPattern(decl.id, kind === "var" ? BIND_VAR : BIND_LEXICAL, false); + }; + + var FUNC_STATEMENT = 1, FUNC_HANGING_STATEMENT = 2, FUNC_NULLABLE_ID = 4; + + // Parse a function declaration or literal (depending on the + // `statement & FUNC_STATEMENT`). + + // Remove `allowExpressionBody` for 7.0.0, as it is only called with false + pp$8.parseFunction = function(node, statement, allowExpressionBody, isAsync, forInit) { + this.initFunction(node); + if (this.options.ecmaVersion >= 9 || this.options.ecmaVersion >= 6 && !isAsync) { + if (this.type === types$1.star && (statement & FUNC_HANGING_STATEMENT)) + { this.unexpected(); } + node.generator = this.eat(types$1.star); + } + if (this.options.ecmaVersion >= 8) + { node.async = !!isAsync; } + + if (statement & FUNC_STATEMENT) { + node.id = (statement & FUNC_NULLABLE_ID) && this.type !== types$1.name ? null : this.parseIdent(); + if (node.id && !(statement & FUNC_HANGING_STATEMENT)) + // If it is a regular function declaration in sloppy mode, then it is + // subject to Annex B semantics (BIND_FUNCTION). Otherwise, the binding + // mode depends on properties of the current scope (see + // treatFunctionsAsVar). + { this.checkLValSimple(node.id, (this.strict || node.generator || node.async) ? this.treatFunctionsAsVar ? BIND_VAR : BIND_LEXICAL : BIND_FUNCTION); } + } + + var oldYieldPos = this.yieldPos, oldAwaitPos = this.awaitPos, oldAwaitIdentPos = this.awaitIdentPos; + this.yieldPos = 0; + this.awaitPos = 0; + this.awaitIdentPos = 0; + this.enterScope(functionFlags(node.async, node.generator)); + + if (!(statement & FUNC_STATEMENT)) + { node.id = this.type === types$1.name ? this.parseIdent() : null; } + + this.parseFunctionParams(node); + this.parseFunctionBody(node, allowExpressionBody, false, forInit); + + this.yieldPos = oldYieldPos; + this.awaitPos = oldAwaitPos; + this.awaitIdentPos = oldAwaitIdentPos; + return this.finishNode(node, (statement & FUNC_STATEMENT) ? "FunctionDeclaration" : "FunctionExpression") + }; + + pp$8.parseFunctionParams = function(node) { + this.expect(types$1.parenL); + node.params = this.parseBindingList(types$1.parenR, false, this.options.ecmaVersion >= 8); + this.checkYieldAwaitInDefaultParams(); + }; + + // Parse a class declaration or literal (depending on the + // `isStatement` parameter). + + pp$8.parseClass = function(node, isStatement) { + this.next(); + + // ecma-262 14.6 Class Definitions + // A class definition is always strict mode code. + var oldStrict = this.strict; + this.strict = true; + + this.parseClassId(node, isStatement); + this.parseClassSuper(node); + var privateNameMap = this.enterClassBody(); + var classBody = this.startNode(); + var hadConstructor = false; + classBody.body = []; + this.expect(types$1.braceL); + while (this.type !== types$1.braceR) { + var element = this.parseClassElement(node.superClass !== null); + if (element) { + classBody.body.push(element); + if (element.type === "MethodDefinition" && element.kind === "constructor") { + if (hadConstructor) { this.raiseRecoverable(element.start, "Duplicate constructor in the same class"); } + hadConstructor = true; + } else if (element.key && element.key.type === "PrivateIdentifier" && isPrivateNameConflicted(privateNameMap, element)) { + this.raiseRecoverable(element.key.start, ("Identifier '#" + (element.key.name) + "' has already been declared")); + } + } + } + this.strict = oldStrict; + this.next(); + node.body = this.finishNode(classBody, "ClassBody"); + this.exitClassBody(); + return this.finishNode(node, isStatement ? "ClassDeclaration" : "ClassExpression") + }; + + pp$8.parseClassElement = function(constructorAllowsSuper) { + if (this.eat(types$1.semi)) { return null } + + var ecmaVersion = this.options.ecmaVersion; + var node = this.startNode(); + var keyName = ""; + var isGenerator = false; + var isAsync = false; + var kind = "method"; + var isStatic = false; + + if (this.eatContextual("static")) { + // Parse static init block + if (ecmaVersion >= 13 && this.eat(types$1.braceL)) { + this.parseClassStaticBlock(node); + return node + } + if (this.isClassElementNameStart() || this.type === types$1.star) { + isStatic = true; + } else { + keyName = "static"; + } + } + node.static = isStatic; + if (!keyName && ecmaVersion >= 8 && this.eatContextual("async")) { + if ((this.isClassElementNameStart() || this.type === types$1.star) && !this.canInsertSemicolon()) { + isAsync = true; + } else { + keyName = "async"; + } + } + if (!keyName && (ecmaVersion >= 9 || !isAsync) && this.eat(types$1.star)) { + isGenerator = true; + } + if (!keyName && !isAsync && !isGenerator) { + var lastValue = this.value; + if (this.eatContextual("get") || this.eatContextual("set")) { + if (this.isClassElementNameStart()) { + kind = lastValue; + } else { + keyName = lastValue; + } + } + } + + // Parse element name + if (keyName) { + // 'async', 'get', 'set', or 'static' were not a keyword contextually. + // The last token is any of those. Make it the element name. + node.computed = false; + node.key = this.startNodeAt(this.lastTokStart, this.lastTokStartLoc); + node.key.name = keyName; + this.finishNode(node.key, "Identifier"); + } else { + this.parseClassElementName(node); + } + + // Parse element value + if (ecmaVersion < 13 || this.type === types$1.parenL || kind !== "method" || isGenerator || isAsync) { + var isConstructor = !node.static && checkKeyName(node, "constructor"); + var allowsDirectSuper = isConstructor && constructorAllowsSuper; + // Couldn't move this check into the 'parseClassMethod' method for backward compatibility. + if (isConstructor && kind !== "method") { this.raise(node.key.start, "Constructor can't have get/set modifier"); } + node.kind = isConstructor ? "constructor" : kind; + this.parseClassMethod(node, isGenerator, isAsync, allowsDirectSuper); + } else { + this.parseClassField(node); + } + + return node + }; + + pp$8.isClassElementNameStart = function() { + return ( + this.type === types$1.name || + this.type === types$1.privateId || + this.type === types$1.num || + this.type === types$1.string || + this.type === types$1.bracketL || + this.type.keyword + ) + }; + + pp$8.parseClassElementName = function(element) { + if (this.type === types$1.privateId) { + if (this.value === "constructor") { + this.raise(this.start, "Classes can't have an element named '#constructor'"); + } + element.computed = false; + element.key = this.parsePrivateIdent(); + } else { + this.parsePropertyName(element); + } + }; + + pp$8.parseClassMethod = function(method, isGenerator, isAsync, allowsDirectSuper) { + // Check key and flags + var key = method.key; + if (method.kind === "constructor") { + if (isGenerator) { this.raise(key.start, "Constructor can't be a generator"); } + if (isAsync) { this.raise(key.start, "Constructor can't be an async method"); } + } else if (method.static && checkKeyName(method, "prototype")) { + this.raise(key.start, "Classes may not have a static property named prototype"); + } + + // Parse value + var value = method.value = this.parseMethod(isGenerator, isAsync, allowsDirectSuper); + + // Check value + if (method.kind === "get" && value.params.length !== 0) + { this.raiseRecoverable(value.start, "getter should have no params"); } + if (method.kind === "set" && value.params.length !== 1) + { this.raiseRecoverable(value.start, "setter should have exactly one param"); } + if (method.kind === "set" && value.params[0].type === "RestElement") + { this.raiseRecoverable(value.params[0].start, "Setter cannot use rest params"); } + + return this.finishNode(method, "MethodDefinition") + }; + + pp$8.parseClassField = function(field) { + if (checkKeyName(field, "constructor")) { + this.raise(field.key.start, "Classes can't have a field named 'constructor'"); + } else if (field.static && checkKeyName(field, "prototype")) { + this.raise(field.key.start, "Classes can't have a static field named 'prototype'"); + } + + if (this.eat(types$1.eq)) { + // To raise SyntaxError if 'arguments' exists in the initializer. + this.enterScope(SCOPE_CLASS_FIELD_INIT | SCOPE_SUPER); + field.value = this.parseMaybeAssign(); + this.exitScope(); + } else { + field.value = null; + } + this.semicolon(); + + return this.finishNode(field, "PropertyDefinition") + }; + + pp$8.parseClassStaticBlock = function(node) { + node.body = []; + + var oldLabels = this.labels; + this.labels = []; + this.enterScope(SCOPE_CLASS_STATIC_BLOCK | SCOPE_SUPER); + while (this.type !== types$1.braceR) { + var stmt = this.parseStatement(null); + node.body.push(stmt); + } + this.next(); + this.exitScope(); + this.labels = oldLabels; + + return this.finishNode(node, "StaticBlock") + }; + + pp$8.parseClassId = function(node, isStatement) { + if (this.type === types$1.name) { + node.id = this.parseIdent(); + if (isStatement) + { this.checkLValSimple(node.id, BIND_LEXICAL, false); } + } else { + if (isStatement === true) + { this.unexpected(); } + node.id = null; + } + }; + + pp$8.parseClassSuper = function(node) { + node.superClass = this.eat(types$1._extends) ? this.parseExprSubscripts(null, false) : null; + }; + + pp$8.enterClassBody = function() { + var element = {declared: Object.create(null), used: []}; + this.privateNameStack.push(element); + return element.declared + }; + + pp$8.exitClassBody = function() { + var ref = this.privateNameStack.pop(); + var declared = ref.declared; + var used = ref.used; + if (!this.options.checkPrivateFields) { return } + var len = this.privateNameStack.length; + var parent = len === 0 ? null : this.privateNameStack[len - 1]; + for (var i = 0; i < used.length; ++i) { + var id = used[i]; + if (!hasOwn(declared, id.name)) { + if (parent) { + parent.used.push(id); + } else { + this.raiseRecoverable(id.start, ("Private field '#" + (id.name) + "' must be declared in an enclosing class")); + } + } + } + }; + + function isPrivateNameConflicted(privateNameMap, element) { + var name = element.key.name; + var curr = privateNameMap[name]; + + var next = "true"; + if (element.type === "MethodDefinition" && (element.kind === "get" || element.kind === "set")) { + next = (element.static ? "s" : "i") + element.kind; + } + + // `class { get #a(){}; static set #a(_){} }` is also conflict. + if ( + curr === "iget" && next === "iset" || + curr === "iset" && next === "iget" || + curr === "sget" && next === "sset" || + curr === "sset" && next === "sget" + ) { + privateNameMap[name] = "true"; + return false + } else if (!curr) { + privateNameMap[name] = next; + return false + } else { + return true + } + } + + function checkKeyName(node, name) { + var computed = node.computed; + var key = node.key; + return !computed && ( + key.type === "Identifier" && key.name === name || + key.type === "Literal" && key.value === name + ) + } + + // Parses module export declaration. + + pp$8.parseExportAllDeclaration = function(node, exports) { + if (this.options.ecmaVersion >= 11) { + if (this.eatContextual("as")) { + node.exported = this.parseModuleExportName(); + this.checkExport(exports, node.exported, this.lastTokStart); + } else { + node.exported = null; + } + } + this.expectContextual("from"); + if (this.type !== types$1.string) { this.unexpected(); } + node.source = this.parseExprAtom(); + if (this.options.ecmaVersion >= 16) + { node.attributes = this.parseWithClause(); } + this.semicolon(); + return this.finishNode(node, "ExportAllDeclaration") + }; + + pp$8.parseExport = function(node, exports) { + this.next(); + // export * from '...' + if (this.eat(types$1.star)) { + return this.parseExportAllDeclaration(node, exports) + } + if (this.eat(types$1._default)) { // export default ... + this.checkExport(exports, "default", this.lastTokStart); + node.declaration = this.parseExportDefaultDeclaration(); + return this.finishNode(node, "ExportDefaultDeclaration") + } + // export var|const|let|function|class ... + if (this.shouldParseExportStatement()) { + node.declaration = this.parseExportDeclaration(node); + if (node.declaration.type === "VariableDeclaration") + { this.checkVariableExport(exports, node.declaration.declarations); } + else + { this.checkExport(exports, node.declaration.id, node.declaration.id.start); } + node.specifiers = []; + node.source = null; + if (this.options.ecmaVersion >= 16) + { node.attributes = []; } + } else { // export { x, y as z } [from '...'] + node.declaration = null; + node.specifiers = this.parseExportSpecifiers(exports); + if (this.eatContextual("from")) { + if (this.type !== types$1.string) { this.unexpected(); } + node.source = this.parseExprAtom(); + if (this.options.ecmaVersion >= 16) + { node.attributes = this.parseWithClause(); } + } else { + for (var i = 0, list = node.specifiers; i < list.length; i += 1) { + // check for keywords used as local names + var spec = list[i]; + + this.checkUnreserved(spec.local); + // check if export is defined + this.checkLocalExport(spec.local); + + if (spec.local.type === "Literal") { + this.raise(spec.local.start, "A string literal cannot be used as an exported binding without `from`."); + } + } + + node.source = null; + if (this.options.ecmaVersion >= 16) + { node.attributes = []; } + } + this.semicolon(); + } + return this.finishNode(node, "ExportNamedDeclaration") + }; + + pp$8.parseExportDeclaration = function(node) { + return this.parseStatement(null) + }; + + pp$8.parseExportDefaultDeclaration = function() { + var isAsync; + if (this.type === types$1._function || (isAsync = this.isAsyncFunction())) { + var fNode = this.startNode(); + this.next(); + if (isAsync) { this.next(); } + return this.parseFunction(fNode, FUNC_STATEMENT | FUNC_NULLABLE_ID, false, isAsync) + } else if (this.type === types$1._class) { + var cNode = this.startNode(); + return this.parseClass(cNode, "nullableID") + } else { + var declaration = this.parseMaybeAssign(); + this.semicolon(); + return declaration + } + }; + + pp$8.checkExport = function(exports, name, pos) { + if (!exports) { return } + if (typeof name !== "string") + { name = name.type === "Identifier" ? name.name : name.value; } + if (hasOwn(exports, name)) + { this.raiseRecoverable(pos, "Duplicate export '" + name + "'"); } + exports[name] = true; + }; + + pp$8.checkPatternExport = function(exports, pat) { + var type = pat.type; + if (type === "Identifier") + { this.checkExport(exports, pat, pat.start); } + else if (type === "ObjectPattern") + { for (var i = 0, list = pat.properties; i < list.length; i += 1) + { + var prop = list[i]; + + this.checkPatternExport(exports, prop); + } } + else if (type === "ArrayPattern") + { for (var i$1 = 0, list$1 = pat.elements; i$1 < list$1.length; i$1 += 1) { + var elt = list$1[i$1]; + + if (elt) { this.checkPatternExport(exports, elt); } + } } + else if (type === "Property") + { this.checkPatternExport(exports, pat.value); } + else if (type === "AssignmentPattern") + { this.checkPatternExport(exports, pat.left); } + else if (type === "RestElement") + { this.checkPatternExport(exports, pat.argument); } + }; + + pp$8.checkVariableExport = function(exports, decls) { + if (!exports) { return } + for (var i = 0, list = decls; i < list.length; i += 1) + { + var decl = list[i]; + + this.checkPatternExport(exports, decl.id); + } + }; + + pp$8.shouldParseExportStatement = function() { + return this.type.keyword === "var" || + this.type.keyword === "const" || + this.type.keyword === "class" || + this.type.keyword === "function" || + this.isLet() || + this.isAsyncFunction() + }; + + // Parses a comma-separated list of module exports. + + pp$8.parseExportSpecifier = function(exports) { + var node = this.startNode(); + node.local = this.parseModuleExportName(); + + node.exported = this.eatContextual("as") ? this.parseModuleExportName() : node.local; + this.checkExport( + exports, + node.exported, + node.exported.start + ); + + return this.finishNode(node, "ExportSpecifier") + }; + + pp$8.parseExportSpecifiers = function(exports) { + var nodes = [], first = true; + // export { x, y as z } [from '...'] + this.expect(types$1.braceL); + while (!this.eat(types$1.braceR)) { + if (!first) { + this.expect(types$1.comma); + if (this.afterTrailingComma(types$1.braceR)) { break } + } else { first = false; } + + nodes.push(this.parseExportSpecifier(exports)); + } + return nodes + }; + + // Parses import declaration. + + pp$8.parseImport = function(node) { + this.next(); + + // import '...' + if (this.type === types$1.string) { + node.specifiers = empty$1; + node.source = this.parseExprAtom(); + } else { + node.specifiers = this.parseImportSpecifiers(); + this.expectContextual("from"); + node.source = this.type === types$1.string ? this.parseExprAtom() : this.unexpected(); + } + if (this.options.ecmaVersion >= 16) + { node.attributes = this.parseWithClause(); } + this.semicolon(); + return this.finishNode(node, "ImportDeclaration") + }; + + // Parses a comma-separated list of module imports. + + pp$8.parseImportSpecifier = function() { + var node = this.startNode(); + node.imported = this.parseModuleExportName(); + + if (this.eatContextual("as")) { + node.local = this.parseIdent(); + } else { + this.checkUnreserved(node.imported); + node.local = node.imported; + } + this.checkLValSimple(node.local, BIND_LEXICAL); + + return this.finishNode(node, "ImportSpecifier") + }; + + pp$8.parseImportDefaultSpecifier = function() { + // import defaultObj, { x, y as z } from '...' + var node = this.startNode(); + node.local = this.parseIdent(); + this.checkLValSimple(node.local, BIND_LEXICAL); + return this.finishNode(node, "ImportDefaultSpecifier") + }; + + pp$8.parseImportNamespaceSpecifier = function() { + var node = this.startNode(); + this.next(); + this.expectContextual("as"); + node.local = this.parseIdent(); + this.checkLValSimple(node.local, BIND_LEXICAL); + return this.finishNode(node, "ImportNamespaceSpecifier") + }; + + pp$8.parseImportSpecifiers = function() { + var nodes = [], first = true; + if (this.type === types$1.name) { + nodes.push(this.parseImportDefaultSpecifier()); + if (!this.eat(types$1.comma)) { return nodes } + } + if (this.type === types$1.star) { + nodes.push(this.parseImportNamespaceSpecifier()); + return nodes + } + this.expect(types$1.braceL); + while (!this.eat(types$1.braceR)) { + if (!first) { + this.expect(types$1.comma); + if (this.afterTrailingComma(types$1.braceR)) { break } + } else { first = false; } + + nodes.push(this.parseImportSpecifier()); + } + return nodes + }; + + pp$8.parseWithClause = function() { + var nodes = []; + if (!this.eat(types$1._with)) { + return nodes + } + this.expect(types$1.braceL); + var attributeKeys = {}; + var first = true; + while (!this.eat(types$1.braceR)) { + if (!first) { + this.expect(types$1.comma); + if (this.afterTrailingComma(types$1.braceR)) { break } + } else { first = false; } + + var attr = this.parseImportAttribute(); + var keyName = attr.key.type === "Identifier" ? attr.key.name : attr.key.value; + if (hasOwn(attributeKeys, keyName)) + { this.raiseRecoverable(attr.key.start, "Duplicate attribute key '" + keyName + "'"); } + attributeKeys[keyName] = true; + nodes.push(attr); + } + return nodes + }; + + pp$8.parseImportAttribute = function() { + var node = this.startNode(); + node.key = this.type === types$1.string ? this.parseExprAtom() : this.parseIdent(this.options.allowReserved !== "never"); + this.expect(types$1.colon); + if (this.type !== types$1.string) { + this.unexpected(); + } + node.value = this.parseExprAtom(); + return this.finishNode(node, "ImportAttribute") + }; + + pp$8.parseModuleExportName = function() { + if (this.options.ecmaVersion >= 13 && this.type === types$1.string) { + var stringLiteral = this.parseLiteral(this.value); + if (loneSurrogate.test(stringLiteral.value)) { + this.raise(stringLiteral.start, "An export name cannot include a lone surrogate."); + } + return stringLiteral + } + return this.parseIdent(true) + }; + + // Set `ExpressionStatement#directive` property for directive prologues. + pp$8.adaptDirectivePrologue = function(statements) { + for (var i = 0; i < statements.length && this.isDirectiveCandidate(statements[i]); ++i) { + statements[i].directive = statements[i].expression.raw.slice(1, -1); + } + }; + pp$8.isDirectiveCandidate = function(statement) { + return ( + this.options.ecmaVersion >= 5 && + statement.type === "ExpressionStatement" && + statement.expression.type === "Literal" && + typeof statement.expression.value === "string" && + // Reject parenthesized strings. + (this.input[statement.start] === "\"" || this.input[statement.start] === "'") + ) + }; + + var pp$7 = Parser.prototype; + + // Convert existing expression atom to assignable pattern + // if possible. + + pp$7.toAssignable = function(node, isBinding, refDestructuringErrors) { + if (this.options.ecmaVersion >= 6 && node) { + switch (node.type) { + case "Identifier": + if (this.inAsync && node.name === "await") + { this.raise(node.start, "Cannot use 'await' as identifier inside an async function"); } + break + + case "ObjectPattern": + case "ArrayPattern": + case "AssignmentPattern": + case "RestElement": + break + + case "ObjectExpression": + node.type = "ObjectPattern"; + if (refDestructuringErrors) { this.checkPatternErrors(refDestructuringErrors, true); } + for (var i = 0, list = node.properties; i < list.length; i += 1) { + var prop = list[i]; + + this.toAssignable(prop, isBinding); + // Early error: + // AssignmentRestProperty[Yield, Await] : + // `...` DestructuringAssignmentTarget[Yield, Await] + // + // It is a Syntax Error if |DestructuringAssignmentTarget| is an |ArrayLiteral| or an |ObjectLiteral|. + if ( + prop.type === "RestElement" && + (prop.argument.type === "ArrayPattern" || prop.argument.type === "ObjectPattern") + ) { + this.raise(prop.argument.start, "Unexpected token"); + } + } + break + + case "Property": + // AssignmentProperty has type === "Property" + if (node.kind !== "init") { this.raise(node.key.start, "Object pattern can't contain getter or setter"); } + this.toAssignable(node.value, isBinding); + break + + case "ArrayExpression": + node.type = "ArrayPattern"; + if (refDestructuringErrors) { this.checkPatternErrors(refDestructuringErrors, true); } + this.toAssignableList(node.elements, isBinding); + break + + case "SpreadElement": + node.type = "RestElement"; + this.toAssignable(node.argument, isBinding); + if (node.argument.type === "AssignmentPattern") + { this.raise(node.argument.start, "Rest elements cannot have a default value"); } + break + + case "AssignmentExpression": + if (node.operator !== "=") { this.raise(node.left.end, "Only '=' operator can be used for specifying default value."); } + node.type = "AssignmentPattern"; + delete node.operator; + this.toAssignable(node.left, isBinding); + break + + case "ParenthesizedExpression": + this.toAssignable(node.expression, isBinding, refDestructuringErrors); + break + + case "ChainExpression": + this.raiseRecoverable(node.start, "Optional chaining cannot appear in left-hand side"); + break + + case "MemberExpression": + if (!isBinding) { break } + + default: + this.raise(node.start, "Assigning to rvalue"); + } + } else if (refDestructuringErrors) { this.checkPatternErrors(refDestructuringErrors, true); } + return node + }; + + // Convert list of expression atoms to binding list. + + pp$7.toAssignableList = function(exprList, isBinding) { + var end = exprList.length; + for (var i = 0; i < end; i++) { + var elt = exprList[i]; + if (elt) { this.toAssignable(elt, isBinding); } + } + if (end) { + var last = exprList[end - 1]; + if (this.options.ecmaVersion === 6 && isBinding && last && last.type === "RestElement" && last.argument.type !== "Identifier") + { this.unexpected(last.argument.start); } + } + return exprList + }; + + // Parses spread element. + + pp$7.parseSpread = function(refDestructuringErrors) { + var node = this.startNode(); + this.next(); + node.argument = this.parseMaybeAssign(false, refDestructuringErrors); + return this.finishNode(node, "SpreadElement") + }; + + pp$7.parseRestBinding = function() { + var node = this.startNode(); + this.next(); + + // RestElement inside of a function parameter must be an identifier + if (this.options.ecmaVersion === 6 && this.type !== types$1.name) + { this.unexpected(); } + + node.argument = this.parseBindingAtom(); + + return this.finishNode(node, "RestElement") + }; + + // Parses lvalue (assignable) atom. + + pp$7.parseBindingAtom = function() { + if (this.options.ecmaVersion >= 6) { + switch (this.type) { + case types$1.bracketL: + var node = this.startNode(); + this.next(); + node.elements = this.parseBindingList(types$1.bracketR, true, true); + return this.finishNode(node, "ArrayPattern") + + case types$1.braceL: + return this.parseObj(true) + } + } + return this.parseIdent() + }; + + pp$7.parseBindingList = function(close, allowEmpty, allowTrailingComma, allowModifiers) { + var elts = [], first = true; + while (!this.eat(close)) { + if (first) { first = false; } + else { this.expect(types$1.comma); } + if (allowEmpty && this.type === types$1.comma) { + elts.push(null); + } else if (allowTrailingComma && this.afterTrailingComma(close)) { + break + } else if (this.type === types$1.ellipsis) { + var rest = this.parseRestBinding(); + this.parseBindingListItem(rest); + elts.push(rest); + if (this.type === types$1.comma) { this.raiseRecoverable(this.start, "Comma is not permitted after the rest element"); } + this.expect(close); + break + } else { + elts.push(this.parseAssignableListItem(allowModifiers)); + } + } + return elts + }; + + pp$7.parseAssignableListItem = function(allowModifiers) { + var elem = this.parseMaybeDefault(this.start, this.startLoc); + this.parseBindingListItem(elem); + return elem + }; + + pp$7.parseBindingListItem = function(param) { + return param + }; + + // Parses assignment pattern around given atom if possible. + + pp$7.parseMaybeDefault = function(startPos, startLoc, left) { + left = left || this.parseBindingAtom(); + if (this.options.ecmaVersion < 6 || !this.eat(types$1.eq)) { return left } + var node = this.startNodeAt(startPos, startLoc); + node.left = left; + node.right = this.parseMaybeAssign(); + return this.finishNode(node, "AssignmentPattern") + }; + + // The following three functions all verify that a node is an lvalue — + // something that can be bound, or assigned to. In order to do so, they perform + // a variety of checks: + // + // - Check that none of the bound/assigned-to identifiers are reserved words. + // - Record name declarations for bindings in the appropriate scope. + // - Check duplicate argument names, if checkClashes is set. + // + // If a complex binding pattern is encountered (e.g., object and array + // destructuring), the entire pattern is recursively checked. + // + // There are three versions of checkLVal*() appropriate for different + // circumstances: + // + // - checkLValSimple() shall be used if the syntactic construct supports + // nothing other than identifiers and member expressions. Parenthesized + // expressions are also correctly handled. This is generally appropriate for + // constructs for which the spec says + // + // > It is a Syntax Error if AssignmentTargetType of [the production] is not + // > simple. + // + // It is also appropriate for checking if an identifier is valid and not + // defined elsewhere, like import declarations or function/class identifiers. + // + // Examples where this is used include: + // a += …; + // import a from '…'; + // where a is the node to be checked. + // + // - checkLValPattern() shall be used if the syntactic construct supports + // anything checkLValSimple() supports, as well as object and array + // destructuring patterns. This is generally appropriate for constructs for + // which the spec says + // + // > It is a Syntax Error if [the production] is neither an ObjectLiteral nor + // > an ArrayLiteral and AssignmentTargetType of [the production] is not + // > simple. + // + // Examples where this is used include: + // (a = …); + // const a = …; + // try { … } catch (a) { … } + // where a is the node to be checked. + // + // - checkLValInnerPattern() shall be used if the syntactic construct supports + // anything checkLValPattern() supports, as well as default assignment + // patterns, rest elements, and other constructs that may appear within an + // object or array destructuring pattern. + // + // As a special case, function parameters also use checkLValInnerPattern(), + // as they also support defaults and rest constructs. + // + // These functions deliberately support both assignment and binding constructs, + // as the logic for both is exceedingly similar. If the node is the target of + // an assignment, then bindingType should be set to BIND_NONE. Otherwise, it + // should be set to the appropriate BIND_* constant, like BIND_VAR or + // BIND_LEXICAL. + // + // If the function is called with a non-BIND_NONE bindingType, then + // additionally a checkClashes object may be specified to allow checking for + // duplicate argument names. checkClashes is ignored if the provided construct + // is an assignment (i.e., bindingType is BIND_NONE). + + pp$7.checkLValSimple = function(expr, bindingType, checkClashes) { + if ( bindingType === void 0 ) bindingType = BIND_NONE; + + var isBind = bindingType !== BIND_NONE; + + switch (expr.type) { + case "Identifier": + if (this.strict && this.reservedWordsStrictBind.test(expr.name)) + { this.raiseRecoverable(expr.start, (isBind ? "Binding " : "Assigning to ") + expr.name + " in strict mode"); } + if (isBind) { + if (bindingType === BIND_LEXICAL && expr.name === "let") + { this.raiseRecoverable(expr.start, "let is disallowed as a lexically bound name"); } + if (checkClashes) { + if (hasOwn(checkClashes, expr.name)) + { this.raiseRecoverable(expr.start, "Argument name clash"); } + checkClashes[expr.name] = true; + } + if (bindingType !== BIND_OUTSIDE) { this.declareName(expr.name, bindingType, expr.start); } + } + break + + case "ChainExpression": + this.raiseRecoverable(expr.start, "Optional chaining cannot appear in left-hand side"); + break + + case "MemberExpression": + if (isBind) { this.raiseRecoverable(expr.start, "Binding member expression"); } + break + + case "ParenthesizedExpression": + if (isBind) { this.raiseRecoverable(expr.start, "Binding parenthesized expression"); } + return this.checkLValSimple(expr.expression, bindingType, checkClashes) + + default: + this.raise(expr.start, (isBind ? "Binding" : "Assigning to") + " rvalue"); + } + }; + + pp$7.checkLValPattern = function(expr, bindingType, checkClashes) { + if ( bindingType === void 0 ) bindingType = BIND_NONE; + + switch (expr.type) { + case "ObjectPattern": + for (var i = 0, list = expr.properties; i < list.length; i += 1) { + var prop = list[i]; + + this.checkLValInnerPattern(prop, bindingType, checkClashes); + } + break + + case "ArrayPattern": + for (var i$1 = 0, list$1 = expr.elements; i$1 < list$1.length; i$1 += 1) { + var elem = list$1[i$1]; + + if (elem) { this.checkLValInnerPattern(elem, bindingType, checkClashes); } + } + break + + default: + this.checkLValSimple(expr, bindingType, checkClashes); + } + }; + + pp$7.checkLValInnerPattern = function(expr, bindingType, checkClashes) { + if ( bindingType === void 0 ) bindingType = BIND_NONE; + + switch (expr.type) { + case "Property": + // AssignmentProperty has type === "Property" + this.checkLValInnerPattern(expr.value, bindingType, checkClashes); + break + + case "AssignmentPattern": + this.checkLValPattern(expr.left, bindingType, checkClashes); + break + + case "RestElement": + this.checkLValPattern(expr.argument, bindingType, checkClashes); + break + + default: + this.checkLValPattern(expr, bindingType, checkClashes); + } + }; + + // The algorithm used to determine whether a regexp can appear at a + // given point in the program is loosely based on sweet.js' approach. + // See https://github.com/mozilla/sweet.js/wiki/design + + + var TokContext = function TokContext(token, isExpr, preserveSpace, override, generator) { + this.token = token; + this.isExpr = !!isExpr; + this.preserveSpace = !!preserveSpace; + this.override = override; + this.generator = !!generator; + }; + + var types = { + b_stat: new TokContext("{", false), + b_expr: new TokContext("{", true), + b_tmpl: new TokContext("${", false), + p_stat: new TokContext("(", false), + p_expr: new TokContext("(", true), + q_tmpl: new TokContext("`", true, true, function (p) { return p.tryReadTemplateToken(); }), + f_stat: new TokContext("function", false), + f_expr: new TokContext("function", true), + f_expr_gen: new TokContext("function", true, false, null, true), + f_gen: new TokContext("function", false, false, null, true) + }; + + var pp$6 = Parser.prototype; + + pp$6.initialContext = function() { + return [types.b_stat] + }; + + pp$6.curContext = function() { + return this.context[this.context.length - 1] + }; + + pp$6.braceIsBlock = function(prevType) { + var parent = this.curContext(); + if (parent === types.f_expr || parent === types.f_stat) + { return true } + if (prevType === types$1.colon && (parent === types.b_stat || parent === types.b_expr)) + { return !parent.isExpr } + + // The check for `tt.name && exprAllowed` detects whether we are + // after a `yield` or `of` construct. See the `updateContext` for + // `tt.name`. + if (prevType === types$1._return || prevType === types$1.name && this.exprAllowed) + { return lineBreak.test(this.input.slice(this.lastTokEnd, this.start)) } + if (prevType === types$1._else || prevType === types$1.semi || prevType === types$1.eof || prevType === types$1.parenR || prevType === types$1.arrow) + { return true } + if (prevType === types$1.braceL) + { return parent === types.b_stat } + if (prevType === types$1._var || prevType === types$1._const || prevType === types$1.name) + { return false } + return !this.exprAllowed + }; + + pp$6.inGeneratorContext = function() { + for (var i = this.context.length - 1; i >= 1; i--) { + var context = this.context[i]; + if (context.token === "function") + { return context.generator } + } + return false + }; + + pp$6.updateContext = function(prevType) { + var update, type = this.type; + if (type.keyword && prevType === types$1.dot) + { this.exprAllowed = false; } + else if (update = type.updateContext) + { update.call(this, prevType); } + else + { this.exprAllowed = type.beforeExpr; } + }; + + // Used to handle edge cases when token context could not be inferred correctly during tokenization phase + + pp$6.overrideContext = function(tokenCtx) { + if (this.curContext() !== tokenCtx) { + this.context[this.context.length - 1] = tokenCtx; + } + }; + + // Token-specific context update code + + types$1.parenR.updateContext = types$1.braceR.updateContext = function() { + if (this.context.length === 1) { + this.exprAllowed = true; + return + } + var out = this.context.pop(); + if (out === types.b_stat && this.curContext().token === "function") { + out = this.context.pop(); + } + this.exprAllowed = !out.isExpr; + }; + + types$1.braceL.updateContext = function(prevType) { + this.context.push(this.braceIsBlock(prevType) ? types.b_stat : types.b_expr); + this.exprAllowed = true; + }; + + types$1.dollarBraceL.updateContext = function() { + this.context.push(types.b_tmpl); + this.exprAllowed = true; + }; + + types$1.parenL.updateContext = function(prevType) { + var statementParens = prevType === types$1._if || prevType === types$1._for || prevType === types$1._with || prevType === types$1._while; + this.context.push(statementParens ? types.p_stat : types.p_expr); + this.exprAllowed = true; + }; + + types$1.incDec.updateContext = function() { + // tokExprAllowed stays unchanged + }; + + types$1._function.updateContext = types$1._class.updateContext = function(prevType) { + if (prevType.beforeExpr && prevType !== types$1._else && + !(prevType === types$1.semi && this.curContext() !== types.p_stat) && + !(prevType === types$1._return && lineBreak.test(this.input.slice(this.lastTokEnd, this.start))) && + !((prevType === types$1.colon || prevType === types$1.braceL) && this.curContext() === types.b_stat)) + { this.context.push(types.f_expr); } + else + { this.context.push(types.f_stat); } + this.exprAllowed = false; + }; + + types$1.colon.updateContext = function() { + if (this.curContext().token === "function") { this.context.pop(); } + this.exprAllowed = true; + }; + + types$1.backQuote.updateContext = function() { + if (this.curContext() === types.q_tmpl) + { this.context.pop(); } + else + { this.context.push(types.q_tmpl); } + this.exprAllowed = false; + }; + + types$1.star.updateContext = function(prevType) { + if (prevType === types$1._function) { + var index = this.context.length - 1; + if (this.context[index] === types.f_expr) + { this.context[index] = types.f_expr_gen; } + else + { this.context[index] = types.f_gen; } + } + this.exprAllowed = true; + }; + + types$1.name.updateContext = function(prevType) { + var allowed = false; + if (this.options.ecmaVersion >= 6 && prevType !== types$1.dot) { + if (this.value === "of" && !this.exprAllowed || + this.value === "yield" && this.inGeneratorContext()) + { allowed = true; } + } + this.exprAllowed = allowed; + }; + + // A recursive descent parser operates by defining functions for all + // syntactic elements, and recursively calling those, each function + // advancing the input stream and returning an AST node. Precedence + // of constructs (for example, the fact that `!x[1]` means `!(x[1])` + // instead of `(!x)[1]` is handled by the fact that the parser + // function that parses unary prefix operators is called first, and + // in turn calls the function that parses `[]` subscripts — that + // way, it'll receive the node for `x[1]` already parsed, and wraps + // *that* in the unary operator node. + // + // Acorn uses an [operator precedence parser][opp] to handle binary + // operator precedence, because it is much more compact than using + // the technique outlined above, which uses different, nesting + // functions to specify precedence, for all of the ten binary + // precedence levels that JavaScript defines. + // + // [opp]: http://en.wikipedia.org/wiki/Operator-precedence_parser + + + var pp$5 = Parser.prototype; + + // Check if property name clashes with already added. + // Object/class getters and setters are not allowed to clash — + // either with each other or with an init property — and in + // strict mode, init properties are also not allowed to be repeated. + + pp$5.checkPropClash = function(prop, propHash, refDestructuringErrors) { + if (this.options.ecmaVersion >= 9 && prop.type === "SpreadElement") + { return } + if (this.options.ecmaVersion >= 6 && (prop.computed || prop.method || prop.shorthand)) + { return } + var key = prop.key; + var name; + switch (key.type) { + case "Identifier": name = key.name; break + case "Literal": name = String(key.value); break + default: return + } + var kind = prop.kind; + if (this.options.ecmaVersion >= 6) { + if (name === "__proto__" && kind === "init") { + if (propHash.proto) { + if (refDestructuringErrors) { + if (refDestructuringErrors.doubleProto < 0) { + refDestructuringErrors.doubleProto = key.start; + } + } else { + this.raiseRecoverable(key.start, "Redefinition of __proto__ property"); + } + } + propHash.proto = true; + } + return + } + name = "$" + name; + var other = propHash[name]; + if (other) { + var redefinition; + if (kind === "init") { + redefinition = this.strict && other.init || other.get || other.set; + } else { + redefinition = other.init || other[kind]; + } + if (redefinition) + { this.raiseRecoverable(key.start, "Redefinition of property"); } + } else { + other = propHash[name] = { + init: false, + get: false, + set: false + }; + } + other[kind] = true; + }; + + // ### Expression parsing + + // These nest, from the most general expression type at the top to + // 'atomic', nondivisible expression types at the bottom. Most of + // the functions will simply let the function(s) below them parse, + // and, *if* the syntactic construct they handle is present, wrap + // the AST node that the inner parser gave them in another node. + + // Parse a full expression. The optional arguments are used to + // forbid the `in` operator (in for loops initalization expressions) + // and provide reference for storing '=' operator inside shorthand + // property assignment in contexts where both object expression + // and object pattern might appear (so it's possible to raise + // delayed syntax error at correct position). + + pp$5.parseExpression = function(forInit, refDestructuringErrors) { + var startPos = this.start, startLoc = this.startLoc; + var expr = this.parseMaybeAssign(forInit, refDestructuringErrors); + if (this.type === types$1.comma) { + var node = this.startNodeAt(startPos, startLoc); + node.expressions = [expr]; + while (this.eat(types$1.comma)) { node.expressions.push(this.parseMaybeAssign(forInit, refDestructuringErrors)); } + return this.finishNode(node, "SequenceExpression") + } + return expr + }; + + // Parse an assignment expression. This includes applications of + // operators like `+=`. + + pp$5.parseMaybeAssign = function(forInit, refDestructuringErrors, afterLeftParse) { + if (this.isContextual("yield")) { + if (this.inGenerator) { return this.parseYield(forInit) } + // The tokenizer will assume an expression is allowed after + // `yield`, but this isn't that kind of yield + else { this.exprAllowed = false; } + } + + var ownDestructuringErrors = false, oldParenAssign = -1, oldTrailingComma = -1, oldDoubleProto = -1; + if (refDestructuringErrors) { + oldParenAssign = refDestructuringErrors.parenthesizedAssign; + oldTrailingComma = refDestructuringErrors.trailingComma; + oldDoubleProto = refDestructuringErrors.doubleProto; + refDestructuringErrors.parenthesizedAssign = refDestructuringErrors.trailingComma = -1; + } else { + refDestructuringErrors = new DestructuringErrors; + ownDestructuringErrors = true; + } + + var startPos = this.start, startLoc = this.startLoc; + if (this.type === types$1.parenL || this.type === types$1.name) { + this.potentialArrowAt = this.start; + this.potentialArrowInForAwait = forInit === "await"; + } + var left = this.parseMaybeConditional(forInit, refDestructuringErrors); + if (afterLeftParse) { left = afterLeftParse.call(this, left, startPos, startLoc); } + if (this.type.isAssign) { + var node = this.startNodeAt(startPos, startLoc); + node.operator = this.value; + if (this.type === types$1.eq) + { left = this.toAssignable(left, false, refDestructuringErrors); } + if (!ownDestructuringErrors) { + refDestructuringErrors.parenthesizedAssign = refDestructuringErrors.trailingComma = refDestructuringErrors.doubleProto = -1; + } + if (refDestructuringErrors.shorthandAssign >= left.start) + { refDestructuringErrors.shorthandAssign = -1; } // reset because shorthand default was used correctly + if (this.type === types$1.eq) + { this.checkLValPattern(left); } + else + { this.checkLValSimple(left); } + node.left = left; + this.next(); + node.right = this.parseMaybeAssign(forInit); + if (oldDoubleProto > -1) { refDestructuringErrors.doubleProto = oldDoubleProto; } + return this.finishNode(node, "AssignmentExpression") + } else { + if (ownDestructuringErrors) { this.checkExpressionErrors(refDestructuringErrors, true); } + } + if (oldParenAssign > -1) { refDestructuringErrors.parenthesizedAssign = oldParenAssign; } + if (oldTrailingComma > -1) { refDestructuringErrors.trailingComma = oldTrailingComma; } + return left + }; + + // Parse a ternary conditional (`?:`) operator. + + pp$5.parseMaybeConditional = function(forInit, refDestructuringErrors) { + var startPos = this.start, startLoc = this.startLoc; + var expr = this.parseExprOps(forInit, refDestructuringErrors); + if (this.checkExpressionErrors(refDestructuringErrors)) { return expr } + if (this.eat(types$1.question)) { + var node = this.startNodeAt(startPos, startLoc); + node.test = expr; + node.consequent = this.parseMaybeAssign(); + this.expect(types$1.colon); + node.alternate = this.parseMaybeAssign(forInit); + return this.finishNode(node, "ConditionalExpression") + } + return expr + }; + + // Start the precedence parser. + + pp$5.parseExprOps = function(forInit, refDestructuringErrors) { + var startPos = this.start, startLoc = this.startLoc; + var expr = this.parseMaybeUnary(refDestructuringErrors, false, false, forInit); + if (this.checkExpressionErrors(refDestructuringErrors)) { return expr } + return expr.start === startPos && expr.type === "ArrowFunctionExpression" ? expr : this.parseExprOp(expr, startPos, startLoc, -1, forInit) + }; + + // Parse binary operators with the operator precedence parsing + // algorithm. `left` is the left-hand side of the operator. + // `minPrec` provides context that allows the function to stop and + // defer further parser to one of its callers when it encounters an + // operator that has a lower precedence than the set it is parsing. + + pp$5.parseExprOp = function(left, leftStartPos, leftStartLoc, minPrec, forInit) { + var prec = this.type.binop; + if (prec != null && (!forInit || this.type !== types$1._in)) { + if (prec > minPrec) { + var logical = this.type === types$1.logicalOR || this.type === types$1.logicalAND; + var coalesce = this.type === types$1.coalesce; + if (coalesce) { + // Handle the precedence of `tt.coalesce` as equal to the range of logical expressions. + // In other words, `node.right` shouldn't contain logical expressions in order to check the mixed error. + prec = types$1.logicalAND.binop; + } + var op = this.value; + this.next(); + var startPos = this.start, startLoc = this.startLoc; + var right = this.parseExprOp(this.parseMaybeUnary(null, false, false, forInit), startPos, startLoc, prec, forInit); + var node = this.buildBinary(leftStartPos, leftStartLoc, left, right, op, logical || coalesce); + if ((logical && this.type === types$1.coalesce) || (coalesce && (this.type === types$1.logicalOR || this.type === types$1.logicalAND))) { + this.raiseRecoverable(this.start, "Logical expressions and coalesce expressions cannot be mixed. Wrap either by parentheses"); + } + return this.parseExprOp(node, leftStartPos, leftStartLoc, minPrec, forInit) + } + } + return left + }; + + pp$5.buildBinary = function(startPos, startLoc, left, right, op, logical) { + if (right.type === "PrivateIdentifier") { this.raise(right.start, "Private identifier can only be left side of binary expression"); } + var node = this.startNodeAt(startPos, startLoc); + node.left = left; + node.operator = op; + node.right = right; + return this.finishNode(node, logical ? "LogicalExpression" : "BinaryExpression") + }; + + // Parse unary operators, both prefix and postfix. + + pp$5.parseMaybeUnary = function(refDestructuringErrors, sawUnary, incDec, forInit) { + var startPos = this.start, startLoc = this.startLoc, expr; + if (this.isContextual("await") && this.canAwait) { + expr = this.parseAwait(forInit); + sawUnary = true; + } else if (this.type.prefix) { + var node = this.startNode(), update = this.type === types$1.incDec; + node.operator = this.value; + node.prefix = true; + this.next(); + node.argument = this.parseMaybeUnary(null, true, update, forInit); + this.checkExpressionErrors(refDestructuringErrors, true); + if (update) { this.checkLValSimple(node.argument); } + else if (this.strict && node.operator === "delete" && isLocalVariableAccess(node.argument)) + { this.raiseRecoverable(node.start, "Deleting local variable in strict mode"); } + else if (node.operator === "delete" && isPrivateFieldAccess(node.argument)) + { this.raiseRecoverable(node.start, "Private fields can not be deleted"); } + else { sawUnary = true; } + expr = this.finishNode(node, update ? "UpdateExpression" : "UnaryExpression"); + } else if (!sawUnary && this.type === types$1.privateId) { + if ((forInit || this.privateNameStack.length === 0) && this.options.checkPrivateFields) { this.unexpected(); } + expr = this.parsePrivateIdent(); + // only could be private fields in 'in', such as #x in obj + if (this.type !== types$1._in) { this.unexpected(); } + } else { + expr = this.parseExprSubscripts(refDestructuringErrors, forInit); + if (this.checkExpressionErrors(refDestructuringErrors)) { return expr } + while (this.type.postfix && !this.canInsertSemicolon()) { + var node$1 = this.startNodeAt(startPos, startLoc); + node$1.operator = this.value; + node$1.prefix = false; + node$1.argument = expr; + this.checkLValSimple(expr); + this.next(); + expr = this.finishNode(node$1, "UpdateExpression"); + } + } + + if (!incDec && this.eat(types$1.starstar)) { + if (sawUnary) + { this.unexpected(this.lastTokStart); } + else + { return this.buildBinary(startPos, startLoc, expr, this.parseMaybeUnary(null, false, false, forInit), "**", false) } + } else { + return expr + } + }; + + function isLocalVariableAccess(node) { + return ( + node.type === "Identifier" || + node.type === "ParenthesizedExpression" && isLocalVariableAccess(node.expression) + ) + } + + function isPrivateFieldAccess(node) { + return ( + node.type === "MemberExpression" && node.property.type === "PrivateIdentifier" || + node.type === "ChainExpression" && isPrivateFieldAccess(node.expression) || + node.type === "ParenthesizedExpression" && isPrivateFieldAccess(node.expression) + ) + } + + // Parse call, dot, and `[]`-subscript expressions. + + pp$5.parseExprSubscripts = function(refDestructuringErrors, forInit) { + var startPos = this.start, startLoc = this.startLoc; + var expr = this.parseExprAtom(refDestructuringErrors, forInit); + if (expr.type === "ArrowFunctionExpression" && this.input.slice(this.lastTokStart, this.lastTokEnd) !== ")") + { return expr } + var result = this.parseSubscripts(expr, startPos, startLoc, false, forInit); + if (refDestructuringErrors && result.type === "MemberExpression") { + if (refDestructuringErrors.parenthesizedAssign >= result.start) { refDestructuringErrors.parenthesizedAssign = -1; } + if (refDestructuringErrors.parenthesizedBind >= result.start) { refDestructuringErrors.parenthesizedBind = -1; } + if (refDestructuringErrors.trailingComma >= result.start) { refDestructuringErrors.trailingComma = -1; } + } + return result + }; + + pp$5.parseSubscripts = function(base, startPos, startLoc, noCalls, forInit) { + var maybeAsyncArrow = this.options.ecmaVersion >= 8 && base.type === "Identifier" && base.name === "async" && + this.lastTokEnd === base.end && !this.canInsertSemicolon() && base.end - base.start === 5 && + this.potentialArrowAt === base.start; + var optionalChained = false; + + while (true) { + var element = this.parseSubscript(base, startPos, startLoc, noCalls, maybeAsyncArrow, optionalChained, forInit); + + if (element.optional) { optionalChained = true; } + if (element === base || element.type === "ArrowFunctionExpression") { + if (optionalChained) { + var chainNode = this.startNodeAt(startPos, startLoc); + chainNode.expression = element; + element = this.finishNode(chainNode, "ChainExpression"); + } + return element + } + + base = element; + } + }; + + pp$5.shouldParseAsyncArrow = function() { + return !this.canInsertSemicolon() && this.eat(types$1.arrow) + }; + + pp$5.parseSubscriptAsyncArrow = function(startPos, startLoc, exprList, forInit) { + return this.parseArrowExpression(this.startNodeAt(startPos, startLoc), exprList, true, forInit) + }; + + pp$5.parseSubscript = function(base, startPos, startLoc, noCalls, maybeAsyncArrow, optionalChained, forInit) { + var optionalSupported = this.options.ecmaVersion >= 11; + var optional = optionalSupported && this.eat(types$1.questionDot); + if (noCalls && optional) { this.raise(this.lastTokStart, "Optional chaining cannot appear in the callee of new expressions"); } + + var computed = this.eat(types$1.bracketL); + if (computed || (optional && this.type !== types$1.parenL && this.type !== types$1.backQuote) || this.eat(types$1.dot)) { + var node = this.startNodeAt(startPos, startLoc); + node.object = base; + if (computed) { + node.property = this.parseExpression(); + this.expect(types$1.bracketR); + } else if (this.type === types$1.privateId && base.type !== "Super") { + node.property = this.parsePrivateIdent(); + } else { + node.property = this.parseIdent(this.options.allowReserved !== "never"); + } + node.computed = !!computed; + if (optionalSupported) { + node.optional = optional; + } + base = this.finishNode(node, "MemberExpression"); + } else if (!noCalls && this.eat(types$1.parenL)) { + var refDestructuringErrors = new DestructuringErrors, oldYieldPos = this.yieldPos, oldAwaitPos = this.awaitPos, oldAwaitIdentPos = this.awaitIdentPos; + this.yieldPos = 0; + this.awaitPos = 0; + this.awaitIdentPos = 0; + var exprList = this.parseExprList(types$1.parenR, this.options.ecmaVersion >= 8, false, refDestructuringErrors); + if (maybeAsyncArrow && !optional && this.shouldParseAsyncArrow()) { + this.checkPatternErrors(refDestructuringErrors, false); + this.checkYieldAwaitInDefaultParams(); + if (this.awaitIdentPos > 0) + { this.raise(this.awaitIdentPos, "Cannot use 'await' as identifier inside an async function"); } + this.yieldPos = oldYieldPos; + this.awaitPos = oldAwaitPos; + this.awaitIdentPos = oldAwaitIdentPos; + return this.parseSubscriptAsyncArrow(startPos, startLoc, exprList, forInit) + } + this.checkExpressionErrors(refDestructuringErrors, true); + this.yieldPos = oldYieldPos || this.yieldPos; + this.awaitPos = oldAwaitPos || this.awaitPos; + this.awaitIdentPos = oldAwaitIdentPos || this.awaitIdentPos; + var node$1 = this.startNodeAt(startPos, startLoc); + node$1.callee = base; + node$1.arguments = exprList; + if (optionalSupported) { + node$1.optional = optional; + } + base = this.finishNode(node$1, "CallExpression"); + } else if (this.type === types$1.backQuote) { + if (optional || optionalChained) { + this.raise(this.start, "Optional chaining cannot appear in the tag of tagged template expressions"); + } + var node$2 = this.startNodeAt(startPos, startLoc); + node$2.tag = base; + node$2.quasi = this.parseTemplate({isTagged: true}); + base = this.finishNode(node$2, "TaggedTemplateExpression"); + } + return base + }; + + // Parse an atomic expression — either a single token that is an + // expression, an expression started by a keyword like `function` or + // `new`, or an expression wrapped in punctuation like `()`, `[]`, + // or `{}`. + + pp$5.parseExprAtom = function(refDestructuringErrors, forInit, forNew) { + // If a division operator appears in an expression position, the + // tokenizer got confused, and we force it to read a regexp instead. + if (this.type === types$1.slash) { this.readRegexp(); } + + var node, canBeArrow = this.potentialArrowAt === this.start; + switch (this.type) { + case types$1._super: + if (!this.allowSuper) + { this.raise(this.start, "'super' keyword outside a method"); } + node = this.startNode(); + this.next(); + if (this.type === types$1.parenL && !this.allowDirectSuper) + { this.raise(node.start, "super() call outside constructor of a subclass"); } + // The `super` keyword can appear at below: + // SuperProperty: + // super [ Expression ] + // super . IdentifierName + // SuperCall: + // super ( Arguments ) + if (this.type !== types$1.dot && this.type !== types$1.bracketL && this.type !== types$1.parenL) + { this.unexpected(); } + return this.finishNode(node, "Super") + + case types$1._this: + node = this.startNode(); + this.next(); + return this.finishNode(node, "ThisExpression") + + case types$1.name: + var startPos = this.start, startLoc = this.startLoc, containsEsc = this.containsEsc; + var id = this.parseIdent(false); + if (this.options.ecmaVersion >= 8 && !containsEsc && id.name === "async" && !this.canInsertSemicolon() && this.eat(types$1._function)) { + this.overrideContext(types.f_expr); + return this.parseFunction(this.startNodeAt(startPos, startLoc), 0, false, true, forInit) + } + if (canBeArrow && !this.canInsertSemicolon()) { + if (this.eat(types$1.arrow)) + { return this.parseArrowExpression(this.startNodeAt(startPos, startLoc), [id], false, forInit) } + if (this.options.ecmaVersion >= 8 && id.name === "async" && this.type === types$1.name && !containsEsc && + (!this.potentialArrowInForAwait || this.value !== "of" || this.containsEsc)) { + id = this.parseIdent(false); + if (this.canInsertSemicolon() || !this.eat(types$1.arrow)) + { this.unexpected(); } + return this.parseArrowExpression(this.startNodeAt(startPos, startLoc), [id], true, forInit) + } + } + return id + + case types$1.regexp: + var value = this.value; + node = this.parseLiteral(value.value); + node.regex = {pattern: value.pattern, flags: value.flags}; + return node + + case types$1.num: case types$1.string: + return this.parseLiteral(this.value) + + case types$1._null: case types$1._true: case types$1._false: + node = this.startNode(); + node.value = this.type === types$1._null ? null : this.type === types$1._true; + node.raw = this.type.keyword; + this.next(); + return this.finishNode(node, "Literal") + + case types$1.parenL: + var start = this.start, expr = this.parseParenAndDistinguishExpression(canBeArrow, forInit); + if (refDestructuringErrors) { + if (refDestructuringErrors.parenthesizedAssign < 0 && !this.isSimpleAssignTarget(expr)) + { refDestructuringErrors.parenthesizedAssign = start; } + if (refDestructuringErrors.parenthesizedBind < 0) + { refDestructuringErrors.parenthesizedBind = start; } + } + return expr + + case types$1.bracketL: + node = this.startNode(); + this.next(); + node.elements = this.parseExprList(types$1.bracketR, true, true, refDestructuringErrors); + return this.finishNode(node, "ArrayExpression") + + case types$1.braceL: + this.overrideContext(types.b_expr); + return this.parseObj(false, refDestructuringErrors) + + case types$1._function: + node = this.startNode(); + this.next(); + return this.parseFunction(node, 0) + + case types$1._class: + return this.parseClass(this.startNode(), false) + + case types$1._new: + return this.parseNew() + + case types$1.backQuote: + return this.parseTemplate() + + case types$1._import: + if (this.options.ecmaVersion >= 11) { + return this.parseExprImport(forNew) + } else { + return this.unexpected() + } + + default: + return this.parseExprAtomDefault() + } + }; + + pp$5.parseExprAtomDefault = function() { + this.unexpected(); + }; + + pp$5.parseExprImport = function(forNew) { + var node = this.startNode(); + + // Consume `import` as an identifier for `import.meta`. + // Because `this.parseIdent(true)` doesn't check escape sequences, it needs the check of `this.containsEsc`. + if (this.containsEsc) { this.raiseRecoverable(this.start, "Escape sequence in keyword import"); } + this.next(); + + if (this.type === types$1.parenL && !forNew) { + return this.parseDynamicImport(node) + } else if (this.type === types$1.dot) { + var meta = this.startNodeAt(node.start, node.loc && node.loc.start); + meta.name = "import"; + node.meta = this.finishNode(meta, "Identifier"); + return this.parseImportMeta(node) + } else { + this.unexpected(); + } + }; + + pp$5.parseDynamicImport = function(node) { + this.next(); // skip `(` + + // Parse node.source. + node.source = this.parseMaybeAssign(); + + if (this.options.ecmaVersion >= 16) { + if (!this.eat(types$1.parenR)) { + this.expect(types$1.comma); + if (!this.afterTrailingComma(types$1.parenR)) { + node.options = this.parseMaybeAssign(); + if (!this.eat(types$1.parenR)) { + this.expect(types$1.comma); + if (!this.afterTrailingComma(types$1.parenR)) { + this.unexpected(); + } + } + } else { + node.options = null; + } + } else { + node.options = null; + } + } else { + // Verify ending. + if (!this.eat(types$1.parenR)) { + var errorPos = this.start; + if (this.eat(types$1.comma) && this.eat(types$1.parenR)) { + this.raiseRecoverable(errorPos, "Trailing comma is not allowed in import()"); + } else { + this.unexpected(errorPos); + } + } + } + + return this.finishNode(node, "ImportExpression") + }; + + pp$5.parseImportMeta = function(node) { + this.next(); // skip `.` + + var containsEsc = this.containsEsc; + node.property = this.parseIdent(true); + + if (node.property.name !== "meta") + { this.raiseRecoverable(node.property.start, "The only valid meta property for import is 'import.meta'"); } + if (containsEsc) + { this.raiseRecoverable(node.start, "'import.meta' must not contain escaped characters"); } + if (this.options.sourceType !== "module" && !this.options.allowImportExportEverywhere) + { this.raiseRecoverable(node.start, "Cannot use 'import.meta' outside a module"); } + + return this.finishNode(node, "MetaProperty") + }; + + pp$5.parseLiteral = function(value) { + var node = this.startNode(); + node.value = value; + node.raw = this.input.slice(this.start, this.end); + if (node.raw.charCodeAt(node.raw.length - 1) === 110) + { node.bigint = node.value != null ? node.value.toString() : node.raw.slice(0, -1).replace(/_/g, ""); } + this.next(); + return this.finishNode(node, "Literal") + }; + + pp$5.parseParenExpression = function() { + this.expect(types$1.parenL); + var val = this.parseExpression(); + this.expect(types$1.parenR); + return val + }; + + pp$5.shouldParseArrow = function(exprList) { + return !this.canInsertSemicolon() + }; + + pp$5.parseParenAndDistinguishExpression = function(canBeArrow, forInit) { + var startPos = this.start, startLoc = this.startLoc, val, allowTrailingComma = this.options.ecmaVersion >= 8; + if (this.options.ecmaVersion >= 6) { + this.next(); + + var innerStartPos = this.start, innerStartLoc = this.startLoc; + var exprList = [], first = true, lastIsComma = false; + var refDestructuringErrors = new DestructuringErrors, oldYieldPos = this.yieldPos, oldAwaitPos = this.awaitPos, spreadStart; + this.yieldPos = 0; + this.awaitPos = 0; + // Do not save awaitIdentPos to allow checking awaits nested in parameters + while (this.type !== types$1.parenR) { + first ? first = false : this.expect(types$1.comma); + if (allowTrailingComma && this.afterTrailingComma(types$1.parenR, true)) { + lastIsComma = true; + break + } else if (this.type === types$1.ellipsis) { + spreadStart = this.start; + exprList.push(this.parseParenItem(this.parseRestBinding())); + if (this.type === types$1.comma) { + this.raiseRecoverable( + this.start, + "Comma is not permitted after the rest element" + ); + } + break + } else { + exprList.push(this.parseMaybeAssign(false, refDestructuringErrors, this.parseParenItem)); + } + } + var innerEndPos = this.lastTokEnd, innerEndLoc = this.lastTokEndLoc; + this.expect(types$1.parenR); + + if (canBeArrow && this.shouldParseArrow(exprList) && this.eat(types$1.arrow)) { + this.checkPatternErrors(refDestructuringErrors, false); + this.checkYieldAwaitInDefaultParams(); + this.yieldPos = oldYieldPos; + this.awaitPos = oldAwaitPos; + return this.parseParenArrowList(startPos, startLoc, exprList, forInit) + } + + if (!exprList.length || lastIsComma) { this.unexpected(this.lastTokStart); } + if (spreadStart) { this.unexpected(spreadStart); } + this.checkExpressionErrors(refDestructuringErrors, true); + this.yieldPos = oldYieldPos || this.yieldPos; + this.awaitPos = oldAwaitPos || this.awaitPos; + + if (exprList.length > 1) { + val = this.startNodeAt(innerStartPos, innerStartLoc); + val.expressions = exprList; + this.finishNodeAt(val, "SequenceExpression", innerEndPos, innerEndLoc); + } else { + val = exprList[0]; + } + } else { + val = this.parseParenExpression(); + } + + if (this.options.preserveParens) { + var par = this.startNodeAt(startPos, startLoc); + par.expression = val; + return this.finishNode(par, "ParenthesizedExpression") + } else { + return val + } + }; + + pp$5.parseParenItem = function(item) { + return item + }; + + pp$5.parseParenArrowList = function(startPos, startLoc, exprList, forInit) { + return this.parseArrowExpression(this.startNodeAt(startPos, startLoc), exprList, false, forInit) + }; + + // New's precedence is slightly tricky. It must allow its argument to + // be a `[]` or dot subscript expression, but not a call — at least, + // not without wrapping it in parentheses. Thus, it uses the noCalls + // argument to parseSubscripts to prevent it from consuming the + // argument list. + + var empty = []; + + pp$5.parseNew = function() { + if (this.containsEsc) { this.raiseRecoverable(this.start, "Escape sequence in keyword new"); } + var node = this.startNode(); + this.next(); + if (this.options.ecmaVersion >= 6 && this.type === types$1.dot) { + var meta = this.startNodeAt(node.start, node.loc && node.loc.start); + meta.name = "new"; + node.meta = this.finishNode(meta, "Identifier"); + this.next(); + var containsEsc = this.containsEsc; + node.property = this.parseIdent(true); + if (node.property.name !== "target") + { this.raiseRecoverable(node.property.start, "The only valid meta property for new is 'new.target'"); } + if (containsEsc) + { this.raiseRecoverable(node.start, "'new.target' must not contain escaped characters"); } + if (!this.allowNewDotTarget) + { this.raiseRecoverable(node.start, "'new.target' can only be used in functions and class static block"); } + return this.finishNode(node, "MetaProperty") + } + var startPos = this.start, startLoc = this.startLoc; + node.callee = this.parseSubscripts(this.parseExprAtom(null, false, true), startPos, startLoc, true, false); + if (this.eat(types$1.parenL)) { node.arguments = this.parseExprList(types$1.parenR, this.options.ecmaVersion >= 8, false); } + else { node.arguments = empty; } + return this.finishNode(node, "NewExpression") + }; + + // Parse template expression. + + pp$5.parseTemplateElement = function(ref) { + var isTagged = ref.isTagged; + + var elem = this.startNode(); + if (this.type === types$1.invalidTemplate) { + if (!isTagged) { + this.raiseRecoverable(this.start, "Bad escape sequence in untagged template literal"); + } + elem.value = { + raw: this.value.replace(/\r\n?/g, "\n"), + cooked: null + }; + } else { + elem.value = { + raw: this.input.slice(this.start, this.end).replace(/\r\n?/g, "\n"), + cooked: this.value + }; + } + this.next(); + elem.tail = this.type === types$1.backQuote; + return this.finishNode(elem, "TemplateElement") + }; + + pp$5.parseTemplate = function(ref) { + if ( ref === void 0 ) ref = {}; + var isTagged = ref.isTagged; if ( isTagged === void 0 ) isTagged = false; + + var node = this.startNode(); + this.next(); + node.expressions = []; + var curElt = this.parseTemplateElement({isTagged: isTagged}); + node.quasis = [curElt]; + while (!curElt.tail) { + if (this.type === types$1.eof) { this.raise(this.pos, "Unterminated template literal"); } + this.expect(types$1.dollarBraceL); + node.expressions.push(this.parseExpression()); + this.expect(types$1.braceR); + node.quasis.push(curElt = this.parseTemplateElement({isTagged: isTagged})); + } + this.next(); + return this.finishNode(node, "TemplateLiteral") + }; + + pp$5.isAsyncProp = function(prop) { + return !prop.computed && prop.key.type === "Identifier" && prop.key.name === "async" && + (this.type === types$1.name || this.type === types$1.num || this.type === types$1.string || this.type === types$1.bracketL || this.type.keyword || (this.options.ecmaVersion >= 9 && this.type === types$1.star)) && + !lineBreak.test(this.input.slice(this.lastTokEnd, this.start)) + }; + + // Parse an object literal or binding pattern. + + pp$5.parseObj = function(isPattern, refDestructuringErrors) { + var node = this.startNode(), first = true, propHash = {}; + node.properties = []; + this.next(); + while (!this.eat(types$1.braceR)) { + if (!first) { + this.expect(types$1.comma); + if (this.options.ecmaVersion >= 5 && this.afterTrailingComma(types$1.braceR)) { break } + } else { first = false; } + + var prop = this.parseProperty(isPattern, refDestructuringErrors); + if (!isPattern) { this.checkPropClash(prop, propHash, refDestructuringErrors); } + node.properties.push(prop); + } + return this.finishNode(node, isPattern ? "ObjectPattern" : "ObjectExpression") + }; + + pp$5.parseProperty = function(isPattern, refDestructuringErrors) { + var prop = this.startNode(), isGenerator, isAsync, startPos, startLoc; + if (this.options.ecmaVersion >= 9 && this.eat(types$1.ellipsis)) { + if (isPattern) { + prop.argument = this.parseIdent(false); + if (this.type === types$1.comma) { + this.raiseRecoverable(this.start, "Comma is not permitted after the rest element"); + } + return this.finishNode(prop, "RestElement") + } + // Parse argument. + prop.argument = this.parseMaybeAssign(false, refDestructuringErrors); + // To disallow trailing comma via `this.toAssignable()`. + if (this.type === types$1.comma && refDestructuringErrors && refDestructuringErrors.trailingComma < 0) { + refDestructuringErrors.trailingComma = this.start; + } + // Finish + return this.finishNode(prop, "SpreadElement") + } + if (this.options.ecmaVersion >= 6) { + prop.method = false; + prop.shorthand = false; + if (isPattern || refDestructuringErrors) { + startPos = this.start; + startLoc = this.startLoc; + } + if (!isPattern) + { isGenerator = this.eat(types$1.star); } + } + var containsEsc = this.containsEsc; + this.parsePropertyName(prop); + if (!isPattern && !containsEsc && this.options.ecmaVersion >= 8 && !isGenerator && this.isAsyncProp(prop)) { + isAsync = true; + isGenerator = this.options.ecmaVersion >= 9 && this.eat(types$1.star); + this.parsePropertyName(prop); + } else { + isAsync = false; + } + this.parsePropertyValue(prop, isPattern, isGenerator, isAsync, startPos, startLoc, refDestructuringErrors, containsEsc); + return this.finishNode(prop, "Property") + }; + + pp$5.parseGetterSetter = function(prop) { + var kind = prop.key.name; + this.parsePropertyName(prop); + prop.value = this.parseMethod(false); + prop.kind = kind; + var paramCount = prop.kind === "get" ? 0 : 1; + if (prop.value.params.length !== paramCount) { + var start = prop.value.start; + if (prop.kind === "get") + { this.raiseRecoverable(start, "getter should have no params"); } + else + { this.raiseRecoverable(start, "setter should have exactly one param"); } + } else { + if (prop.kind === "set" && prop.value.params[0].type === "RestElement") + { this.raiseRecoverable(prop.value.params[0].start, "Setter cannot use rest params"); } + } + }; + + pp$5.parsePropertyValue = function(prop, isPattern, isGenerator, isAsync, startPos, startLoc, refDestructuringErrors, containsEsc) { + if ((isGenerator || isAsync) && this.type === types$1.colon) + { this.unexpected(); } + + if (this.eat(types$1.colon)) { + prop.value = isPattern ? this.parseMaybeDefault(this.start, this.startLoc) : this.parseMaybeAssign(false, refDestructuringErrors); + prop.kind = "init"; + } else if (this.options.ecmaVersion >= 6 && this.type === types$1.parenL) { + if (isPattern) { this.unexpected(); } + prop.method = true; + prop.value = this.parseMethod(isGenerator, isAsync); + prop.kind = "init"; + } else if (!isPattern && !containsEsc && + this.options.ecmaVersion >= 5 && !prop.computed && prop.key.type === "Identifier" && + (prop.key.name === "get" || prop.key.name === "set") && + (this.type !== types$1.comma && this.type !== types$1.braceR && this.type !== types$1.eq)) { + if (isGenerator || isAsync) { this.unexpected(); } + this.parseGetterSetter(prop); + } else if (this.options.ecmaVersion >= 6 && !prop.computed && prop.key.type === "Identifier") { + if (isGenerator || isAsync) { this.unexpected(); } + this.checkUnreserved(prop.key); + if (prop.key.name === "await" && !this.awaitIdentPos) + { this.awaitIdentPos = startPos; } + if (isPattern) { + prop.value = this.parseMaybeDefault(startPos, startLoc, this.copyNode(prop.key)); + } else if (this.type === types$1.eq && refDestructuringErrors) { + if (refDestructuringErrors.shorthandAssign < 0) + { refDestructuringErrors.shorthandAssign = this.start; } + prop.value = this.parseMaybeDefault(startPos, startLoc, this.copyNode(prop.key)); + } else { + prop.value = this.copyNode(prop.key); + } + prop.kind = "init"; + prop.shorthand = true; + } else { this.unexpected(); } + }; + + pp$5.parsePropertyName = function(prop) { + if (this.options.ecmaVersion >= 6) { + if (this.eat(types$1.bracketL)) { + prop.computed = true; + prop.key = this.parseMaybeAssign(); + this.expect(types$1.bracketR); + return prop.key + } else { + prop.computed = false; + } + } + return prop.key = this.type === types$1.num || this.type === types$1.string ? this.parseExprAtom() : this.parseIdent(this.options.allowReserved !== "never") + }; + + // Initialize empty function node. + + pp$5.initFunction = function(node) { + node.id = null; + if (this.options.ecmaVersion >= 6) { node.generator = node.expression = false; } + if (this.options.ecmaVersion >= 8) { node.async = false; } + }; + + // Parse object or class method. + + pp$5.parseMethod = function(isGenerator, isAsync, allowDirectSuper) { + var node = this.startNode(), oldYieldPos = this.yieldPos, oldAwaitPos = this.awaitPos, oldAwaitIdentPos = this.awaitIdentPos; + + this.initFunction(node); + if (this.options.ecmaVersion >= 6) + { node.generator = isGenerator; } + if (this.options.ecmaVersion >= 8) + { node.async = !!isAsync; } + + this.yieldPos = 0; + this.awaitPos = 0; + this.awaitIdentPos = 0; + this.enterScope(functionFlags(isAsync, node.generator) | SCOPE_SUPER | (allowDirectSuper ? SCOPE_DIRECT_SUPER : 0)); + + this.expect(types$1.parenL); + node.params = this.parseBindingList(types$1.parenR, false, this.options.ecmaVersion >= 8); + this.checkYieldAwaitInDefaultParams(); + this.parseFunctionBody(node, false, true, false); + + this.yieldPos = oldYieldPos; + this.awaitPos = oldAwaitPos; + this.awaitIdentPos = oldAwaitIdentPos; + return this.finishNode(node, "FunctionExpression") + }; + + // Parse arrow function expression with given parameters. + + pp$5.parseArrowExpression = function(node, params, isAsync, forInit) { + var oldYieldPos = this.yieldPos, oldAwaitPos = this.awaitPos, oldAwaitIdentPos = this.awaitIdentPos; + + this.enterScope(functionFlags(isAsync, false) | SCOPE_ARROW); + this.initFunction(node); + if (this.options.ecmaVersion >= 8) { node.async = !!isAsync; } + + this.yieldPos = 0; + this.awaitPos = 0; + this.awaitIdentPos = 0; + + node.params = this.toAssignableList(params, true); + this.parseFunctionBody(node, true, false, forInit); + + this.yieldPos = oldYieldPos; + this.awaitPos = oldAwaitPos; + this.awaitIdentPos = oldAwaitIdentPos; + return this.finishNode(node, "ArrowFunctionExpression") + }; + + // Parse function body and check parameters. + + pp$5.parseFunctionBody = function(node, isArrowFunction, isMethod, forInit) { + var isExpression = isArrowFunction && this.type !== types$1.braceL; + var oldStrict = this.strict, useStrict = false; + + if (isExpression) { + node.body = this.parseMaybeAssign(forInit); + node.expression = true; + this.checkParams(node, false); + } else { + var nonSimple = this.options.ecmaVersion >= 7 && !this.isSimpleParamList(node.params); + if (!oldStrict || nonSimple) { + useStrict = this.strictDirective(this.end); + // If this is a strict mode function, verify that argument names + // are not repeated, and it does not try to bind the words `eval` + // or `arguments`. + if (useStrict && nonSimple) + { this.raiseRecoverable(node.start, "Illegal 'use strict' directive in function with non-simple parameter list"); } + } + // Start a new scope with regard to labels and the `inFunction` + // flag (restore them to their old value afterwards). + var oldLabels = this.labels; + this.labels = []; + if (useStrict) { this.strict = true; } + + // Add the params to varDeclaredNames to ensure that an error is thrown + // if a let/const declaration in the function clashes with one of the params. + this.checkParams(node, !oldStrict && !useStrict && !isArrowFunction && !isMethod && this.isSimpleParamList(node.params)); + // Ensure the function name isn't a forbidden identifier in strict mode, e.g. 'eval' + if (this.strict && node.id) { this.checkLValSimple(node.id, BIND_OUTSIDE); } + node.body = this.parseBlock(false, undefined, useStrict && !oldStrict); + node.expression = false; + this.adaptDirectivePrologue(node.body.body); + this.labels = oldLabels; + } + this.exitScope(); + }; + + pp$5.isSimpleParamList = function(params) { + for (var i = 0, list = params; i < list.length; i += 1) + { + var param = list[i]; + + if (param.type !== "Identifier") { return false + } } + return true + }; + + // Checks function params for various disallowed patterns such as using "eval" + // or "arguments" and duplicate parameters. + + pp$5.checkParams = function(node, allowDuplicates) { + var nameHash = Object.create(null); + for (var i = 0, list = node.params; i < list.length; i += 1) + { + var param = list[i]; + + this.checkLValInnerPattern(param, BIND_VAR, allowDuplicates ? null : nameHash); + } + }; + + // Parses a comma-separated list of expressions, and returns them as + // an array. `close` is the token type that ends the list, and + // `allowEmpty` can be turned on to allow subsequent commas with + // nothing in between them to be parsed as `null` (which is needed + // for array literals). + + pp$5.parseExprList = function(close, allowTrailingComma, allowEmpty, refDestructuringErrors) { + var elts = [], first = true; + while (!this.eat(close)) { + if (!first) { + this.expect(types$1.comma); + if (allowTrailingComma && this.afterTrailingComma(close)) { break } + } else { first = false; } + + var elt = (void 0); + if (allowEmpty && this.type === types$1.comma) + { elt = null; } + else if (this.type === types$1.ellipsis) { + elt = this.parseSpread(refDestructuringErrors); + if (refDestructuringErrors && this.type === types$1.comma && refDestructuringErrors.trailingComma < 0) + { refDestructuringErrors.trailingComma = this.start; } + } else { + elt = this.parseMaybeAssign(false, refDestructuringErrors); + } + elts.push(elt); + } + return elts + }; + + pp$5.checkUnreserved = function(ref) { + var start = ref.start; + var end = ref.end; + var name = ref.name; + + if (this.inGenerator && name === "yield") + { this.raiseRecoverable(start, "Cannot use 'yield' as identifier inside a generator"); } + if (this.inAsync && name === "await") + { this.raiseRecoverable(start, "Cannot use 'await' as identifier inside an async function"); } + if (!(this.currentThisScope().flags & SCOPE_VAR) && name === "arguments") + { this.raiseRecoverable(start, "Cannot use 'arguments' in class field initializer"); } + if (this.inClassStaticBlock && (name === "arguments" || name === "await")) + { this.raise(start, ("Cannot use " + name + " in class static initialization block")); } + if (this.keywords.test(name)) + { this.raise(start, ("Unexpected keyword '" + name + "'")); } + if (this.options.ecmaVersion < 6 && + this.input.slice(start, end).indexOf("\\") !== -1) { return } + var re = this.strict ? this.reservedWordsStrict : this.reservedWords; + if (re.test(name)) { + if (!this.inAsync && name === "await") + { this.raiseRecoverable(start, "Cannot use keyword 'await' outside an async function"); } + this.raiseRecoverable(start, ("The keyword '" + name + "' is reserved")); + } + }; + + // Parse the next token as an identifier. If `liberal` is true (used + // when parsing properties), it will also convert keywords into + // identifiers. + + pp$5.parseIdent = function(liberal) { + var node = this.parseIdentNode(); + this.next(!!liberal); + this.finishNode(node, "Identifier"); + if (!liberal) { + this.checkUnreserved(node); + if (node.name === "await" && !this.awaitIdentPos) + { this.awaitIdentPos = node.start; } + } + return node + }; + + pp$5.parseIdentNode = function() { + var node = this.startNode(); + if (this.type === types$1.name) { + node.name = this.value; + } else if (this.type.keyword) { + node.name = this.type.keyword; + + // To fix https://github.com/acornjs/acorn/issues/575 + // `class` and `function` keywords push new context into this.context. + // But there is no chance to pop the context if the keyword is consumed as an identifier such as a property name. + // If the previous token is a dot, this does not apply because the context-managing code already ignored the keyword + if ((node.name === "class" || node.name === "function") && + (this.lastTokEnd !== this.lastTokStart + 1 || this.input.charCodeAt(this.lastTokStart) !== 46)) { + this.context.pop(); + } + this.type = types$1.name; + } else { + this.unexpected(); + } + return node + }; + + pp$5.parsePrivateIdent = function() { + var node = this.startNode(); + if (this.type === types$1.privateId) { + node.name = this.value; + } else { + this.unexpected(); + } + this.next(); + this.finishNode(node, "PrivateIdentifier"); + + // For validating existence + if (this.options.checkPrivateFields) { + if (this.privateNameStack.length === 0) { + this.raise(node.start, ("Private field '#" + (node.name) + "' must be declared in an enclosing class")); + } else { + this.privateNameStack[this.privateNameStack.length - 1].used.push(node); + } + } + + return node + }; + + // Parses yield expression inside generator. + + pp$5.parseYield = function(forInit) { + if (!this.yieldPos) { this.yieldPos = this.start; } + + var node = this.startNode(); + this.next(); + if (this.type === types$1.semi || this.canInsertSemicolon() || (this.type !== types$1.star && !this.type.startsExpr)) { + node.delegate = false; + node.argument = null; + } else { + node.delegate = this.eat(types$1.star); + node.argument = this.parseMaybeAssign(forInit); + } + return this.finishNode(node, "YieldExpression") + }; + + pp$5.parseAwait = function(forInit) { + if (!this.awaitPos) { this.awaitPos = this.start; } + + var node = this.startNode(); + this.next(); + node.argument = this.parseMaybeUnary(null, true, false, forInit); + return this.finishNode(node, "AwaitExpression") + }; + + var pp$4 = Parser.prototype; + + // This function is used to raise exceptions on parse errors. It + // takes an offset integer (into the current `input`) to indicate + // the location of the error, attaches the position to the end + // of the error message, and then raises a `SyntaxError` with that + // message. + + pp$4.raise = function(pos, message) { + var loc = getLineInfo(this.input, pos); + message += " (" + loc.line + ":" + loc.column + ")"; + if (this.sourceFile) { + message += " in " + this.sourceFile; + } + var err = new SyntaxError(message); + err.pos = pos; err.loc = loc; err.raisedAt = this.pos; + throw err + }; + + pp$4.raiseRecoverable = pp$4.raise; + + pp$4.curPosition = function() { + if (this.options.locations) { + return new Position(this.curLine, this.pos - this.lineStart) + } + }; + + var pp$3 = Parser.prototype; + + var Scope = function Scope(flags) { + this.flags = flags; + // A list of var-declared names in the current lexical scope + this.var = []; + // A list of lexically-declared names in the current lexical scope + this.lexical = []; + // A list of lexically-declared FunctionDeclaration names in the current lexical scope + this.functions = []; + }; + + // The functions in this module keep track of declared variables in the current scope in order to detect duplicate variable names. + + pp$3.enterScope = function(flags) { + this.scopeStack.push(new Scope(flags)); + }; + + pp$3.exitScope = function() { + this.scopeStack.pop(); + }; + + // The spec says: + // > At the top level of a function, or script, function declarations are + // > treated like var declarations rather than like lexical declarations. + pp$3.treatFunctionsAsVarInScope = function(scope) { + return (scope.flags & SCOPE_FUNCTION) || !this.inModule && (scope.flags & SCOPE_TOP) + }; + + pp$3.declareName = function(name, bindingType, pos) { + var redeclared = false; + if (bindingType === BIND_LEXICAL) { + var scope = this.currentScope(); + redeclared = scope.lexical.indexOf(name) > -1 || scope.functions.indexOf(name) > -1 || scope.var.indexOf(name) > -1; + scope.lexical.push(name); + if (this.inModule && (scope.flags & SCOPE_TOP)) + { delete this.undefinedExports[name]; } + } else if (bindingType === BIND_SIMPLE_CATCH) { + var scope$1 = this.currentScope(); + scope$1.lexical.push(name); + } else if (bindingType === BIND_FUNCTION) { + var scope$2 = this.currentScope(); + if (this.treatFunctionsAsVar) + { redeclared = scope$2.lexical.indexOf(name) > -1; } + else + { redeclared = scope$2.lexical.indexOf(name) > -1 || scope$2.var.indexOf(name) > -1; } + scope$2.functions.push(name); + } else { + for (var i = this.scopeStack.length - 1; i >= 0; --i) { + var scope$3 = this.scopeStack[i]; + if (scope$3.lexical.indexOf(name) > -1 && !((scope$3.flags & SCOPE_SIMPLE_CATCH) && scope$3.lexical[0] === name) || + !this.treatFunctionsAsVarInScope(scope$3) && scope$3.functions.indexOf(name) > -1) { + redeclared = true; + break + } + scope$3.var.push(name); + if (this.inModule && (scope$3.flags & SCOPE_TOP)) + { delete this.undefinedExports[name]; } + if (scope$3.flags & SCOPE_VAR) { break } + } + } + if (redeclared) { this.raiseRecoverable(pos, ("Identifier '" + name + "' has already been declared")); } + }; + + pp$3.checkLocalExport = function(id) { + // scope.functions must be empty as Module code is always strict. + if (this.scopeStack[0].lexical.indexOf(id.name) === -1 && + this.scopeStack[0].var.indexOf(id.name) === -1) { + this.undefinedExports[id.name] = id; + } + }; + + pp$3.currentScope = function() { + return this.scopeStack[this.scopeStack.length - 1] + }; + + pp$3.currentVarScope = function() { + for (var i = this.scopeStack.length - 1;; i--) { + var scope = this.scopeStack[i]; + if (scope.flags & (SCOPE_VAR | SCOPE_CLASS_FIELD_INIT | SCOPE_CLASS_STATIC_BLOCK)) { return scope } + } + }; + + // Could be useful for `this`, `new.target`, `super()`, `super.property`, and `super[property]`. + pp$3.currentThisScope = function() { + for (var i = this.scopeStack.length - 1;; i--) { + var scope = this.scopeStack[i]; + if (scope.flags & (SCOPE_VAR | SCOPE_CLASS_FIELD_INIT | SCOPE_CLASS_STATIC_BLOCK) && + !(scope.flags & SCOPE_ARROW)) { return scope } + } + }; + + var Node = function Node(parser, pos, loc) { + this.type = ""; + this.start = pos; + this.end = 0; + if (parser.options.locations) + { this.loc = new SourceLocation(parser, loc); } + if (parser.options.directSourceFile) + { this.sourceFile = parser.options.directSourceFile; } + if (parser.options.ranges) + { this.range = [pos, 0]; } + }; + + // Start an AST node, attaching a start offset. + + var pp$2 = Parser.prototype; + + pp$2.startNode = function() { + return new Node(this, this.start, this.startLoc) + }; + + pp$2.startNodeAt = function(pos, loc) { + return new Node(this, pos, loc) + }; + + // Finish an AST node, adding `type` and `end` properties. + + function finishNodeAt(node, type, pos, loc) { + node.type = type; + node.end = pos; + if (this.options.locations) + { node.loc.end = loc; } + if (this.options.ranges) + { node.range[1] = pos; } + return node + } + + pp$2.finishNode = function(node, type) { + return finishNodeAt.call(this, node, type, this.lastTokEnd, this.lastTokEndLoc) + }; + + // Finish node at given position + + pp$2.finishNodeAt = function(node, type, pos, loc) { + return finishNodeAt.call(this, node, type, pos, loc) + }; + + pp$2.copyNode = function(node) { + var newNode = new Node(this, node.start, this.startLoc); + for (var prop in node) { newNode[prop] = node[prop]; } + return newNode + }; + + // This file was generated by "bin/generate-unicode-script-values.js". Do not modify manually! + var scriptValuesAddedInUnicode = "Berf Beria_Erfe Gara Garay Gukh Gurung_Khema Hrkt Katakana_Or_Hiragana Kawi Kirat_Rai Krai Nag_Mundari Nagm Ol_Onal Onao Sidetic Sidt Sunu Sunuwar Tai_Yo Tayo Todhri Todr Tolong_Siki Tols Tulu_Tigalari Tutg Unknown Zzzz"; + + // This file contains Unicode properties extracted from the ECMAScript specification. + // The lists are extracted like so: + // $$('#table-binary-unicode-properties > figure > table > tbody > tr > td:nth-child(1) code').map(el => el.innerText) + + // #table-binary-unicode-properties + var ecma9BinaryProperties = "ASCII ASCII_Hex_Digit AHex Alphabetic Alpha Any Assigned Bidi_Control Bidi_C Bidi_Mirrored Bidi_M Case_Ignorable CI Cased Changes_When_Casefolded CWCF Changes_When_Casemapped CWCM Changes_When_Lowercased CWL Changes_When_NFKC_Casefolded CWKCF Changes_When_Titlecased CWT Changes_When_Uppercased CWU Dash Default_Ignorable_Code_Point DI Deprecated Dep Diacritic Dia Emoji Emoji_Component Emoji_Modifier Emoji_Modifier_Base Emoji_Presentation Extender Ext Grapheme_Base Gr_Base Grapheme_Extend Gr_Ext Hex_Digit Hex IDS_Binary_Operator IDSB IDS_Trinary_Operator IDST ID_Continue IDC ID_Start IDS Ideographic Ideo Join_Control Join_C Logical_Order_Exception LOE Lowercase Lower Math Noncharacter_Code_Point NChar Pattern_Syntax Pat_Syn Pattern_White_Space Pat_WS Quotation_Mark QMark Radical Regional_Indicator RI Sentence_Terminal STerm Soft_Dotted SD Terminal_Punctuation Term Unified_Ideograph UIdeo Uppercase Upper Variation_Selector VS White_Space space XID_Continue XIDC XID_Start XIDS"; + var ecma10BinaryProperties = ecma9BinaryProperties + " Extended_Pictographic"; + var ecma11BinaryProperties = ecma10BinaryProperties; + var ecma12BinaryProperties = ecma11BinaryProperties + " EBase EComp EMod EPres ExtPict"; + var ecma13BinaryProperties = ecma12BinaryProperties; + var ecma14BinaryProperties = ecma13BinaryProperties; + + var unicodeBinaryProperties = { + 9: ecma9BinaryProperties, + 10: ecma10BinaryProperties, + 11: ecma11BinaryProperties, + 12: ecma12BinaryProperties, + 13: ecma13BinaryProperties, + 14: ecma14BinaryProperties + }; + + // #table-binary-unicode-properties-of-strings + var ecma14BinaryPropertiesOfStrings = "Basic_Emoji Emoji_Keycap_Sequence RGI_Emoji_Modifier_Sequence RGI_Emoji_Flag_Sequence RGI_Emoji_Tag_Sequence RGI_Emoji_ZWJ_Sequence RGI_Emoji"; + + var unicodeBinaryPropertiesOfStrings = { + 9: "", + 10: "", + 11: "", + 12: "", + 13: "", + 14: ecma14BinaryPropertiesOfStrings + }; + + // #table-unicode-general-category-values + var unicodeGeneralCategoryValues = "Cased_Letter LC Close_Punctuation Pe Connector_Punctuation Pc Control Cc cntrl Currency_Symbol Sc Dash_Punctuation Pd Decimal_Number Nd digit Enclosing_Mark Me Final_Punctuation Pf Format Cf Initial_Punctuation Pi Letter L Letter_Number Nl Line_Separator Zl Lowercase_Letter Ll Mark M Combining_Mark Math_Symbol Sm Modifier_Letter Lm Modifier_Symbol Sk Nonspacing_Mark Mn Number N Open_Punctuation Ps Other C Other_Letter Lo Other_Number No Other_Punctuation Po Other_Symbol So Paragraph_Separator Zp Private_Use Co Punctuation P punct Separator Z Space_Separator Zs Spacing_Mark Mc Surrogate Cs Symbol S Titlecase_Letter Lt Unassigned Cn Uppercase_Letter Lu"; + + // #table-unicode-script-values + var ecma9ScriptValues = "Adlam Adlm Ahom Anatolian_Hieroglyphs Hluw Arabic Arab Armenian Armn Avestan Avst Balinese Bali Bamum Bamu Bassa_Vah Bass Batak Batk Bengali Beng Bhaiksuki Bhks Bopomofo Bopo Brahmi Brah Braille Brai Buginese Bugi Buhid Buhd Canadian_Aboriginal Cans Carian Cari Caucasian_Albanian Aghb Chakma Cakm Cham Cham Cherokee Cher Common Zyyy Coptic Copt Qaac Cuneiform Xsux Cypriot Cprt Cyrillic Cyrl Deseret Dsrt Devanagari Deva Duployan Dupl Egyptian_Hieroglyphs Egyp Elbasan Elba Ethiopic Ethi Georgian Geor Glagolitic Glag Gothic Goth Grantha Gran Greek Grek Gujarati Gujr Gurmukhi Guru Han Hani Hangul Hang Hanunoo Hano Hatran Hatr Hebrew Hebr Hiragana Hira Imperial_Aramaic Armi Inherited Zinh Qaai Inscriptional_Pahlavi Phli Inscriptional_Parthian Prti Javanese Java Kaithi Kthi Kannada Knda Katakana Kana Kayah_Li Kali Kharoshthi Khar Khmer Khmr Khojki Khoj Khudawadi Sind Lao Laoo Latin Latn Lepcha Lepc Limbu Limb Linear_A Lina Linear_B Linb Lisu Lisu Lycian Lyci Lydian Lydi Mahajani Mahj Malayalam Mlym Mandaic Mand Manichaean Mani Marchen Marc Masaram_Gondi Gonm Meetei_Mayek Mtei Mende_Kikakui Mend Meroitic_Cursive Merc Meroitic_Hieroglyphs Mero Miao Plrd Modi Mongolian Mong Mro Mroo Multani Mult Myanmar Mymr Nabataean Nbat New_Tai_Lue Talu Newa Newa Nko Nkoo Nushu Nshu Ogham Ogam Ol_Chiki Olck Old_Hungarian Hung Old_Italic Ital Old_North_Arabian Narb Old_Permic Perm Old_Persian Xpeo Old_South_Arabian Sarb Old_Turkic Orkh Oriya Orya Osage Osge Osmanya Osma Pahawh_Hmong Hmng Palmyrene Palm Pau_Cin_Hau Pauc Phags_Pa Phag Phoenician Phnx Psalter_Pahlavi Phlp Rejang Rjng Runic Runr Samaritan Samr Saurashtra Saur Sharada Shrd Shavian Shaw Siddham Sidd SignWriting Sgnw Sinhala Sinh Sora_Sompeng Sora Soyombo Soyo Sundanese Sund Syloti_Nagri Sylo Syriac Syrc Tagalog Tglg Tagbanwa Tagb Tai_Le Tale Tai_Tham Lana Tai_Viet Tavt Takri Takr Tamil Taml Tangut Tang Telugu Telu Thaana Thaa Thai Thai Tibetan Tibt Tifinagh Tfng Tirhuta Tirh Ugaritic Ugar Vai Vaii Warang_Citi Wara Yi Yiii Zanabazar_Square Zanb"; + var ecma10ScriptValues = ecma9ScriptValues + " Dogra Dogr Gunjala_Gondi Gong Hanifi_Rohingya Rohg Makasar Maka Medefaidrin Medf Old_Sogdian Sogo Sogdian Sogd"; + var ecma11ScriptValues = ecma10ScriptValues + " Elymaic Elym Nandinagari Nand Nyiakeng_Puachue_Hmong Hmnp Wancho Wcho"; + var ecma12ScriptValues = ecma11ScriptValues + " Chorasmian Chrs Diak Dives_Akuru Khitan_Small_Script Kits Yezi Yezidi"; + var ecma13ScriptValues = ecma12ScriptValues + " Cypro_Minoan Cpmn Old_Uyghur Ougr Tangsa Tnsa Toto Vithkuqi Vith"; + var ecma14ScriptValues = ecma13ScriptValues + " " + scriptValuesAddedInUnicode; + + var unicodeScriptValues = { + 9: ecma9ScriptValues, + 10: ecma10ScriptValues, + 11: ecma11ScriptValues, + 12: ecma12ScriptValues, + 13: ecma13ScriptValues, + 14: ecma14ScriptValues + }; + + var data = {}; + function buildUnicodeData(ecmaVersion) { + var d = data[ecmaVersion] = { + binary: wordsRegexp(unicodeBinaryProperties[ecmaVersion] + " " + unicodeGeneralCategoryValues), + binaryOfStrings: wordsRegexp(unicodeBinaryPropertiesOfStrings[ecmaVersion]), + nonBinary: { + General_Category: wordsRegexp(unicodeGeneralCategoryValues), + Script: wordsRegexp(unicodeScriptValues[ecmaVersion]) + } + }; + d.nonBinary.Script_Extensions = d.nonBinary.Script; + + d.nonBinary.gc = d.nonBinary.General_Category; + d.nonBinary.sc = d.nonBinary.Script; + d.nonBinary.scx = d.nonBinary.Script_Extensions; + } + + for (var i = 0, list = [9, 10, 11, 12, 13, 14]; i < list.length; i += 1) { + var ecmaVersion = list[i]; + + buildUnicodeData(ecmaVersion); + } + + var pp$1 = Parser.prototype; + + // Track disjunction structure to determine whether a duplicate + // capture group name is allowed because it is in a separate branch. + var BranchID = function BranchID(parent, base) { + // Parent disjunction branch + this.parent = parent; + // Identifies this set of sibling branches + this.base = base || this; + }; + + BranchID.prototype.separatedFrom = function separatedFrom (alt) { + // A branch is separate from another branch if they or any of + // their parents are siblings in a given disjunction + for (var self = this; self; self = self.parent) { + for (var other = alt; other; other = other.parent) { + if (self.base === other.base && self !== other) { return true } + } + } + return false + }; + + BranchID.prototype.sibling = function sibling () { + return new BranchID(this.parent, this.base) + }; + + var RegExpValidationState = function RegExpValidationState(parser) { + this.parser = parser; + this.validFlags = "gim" + (parser.options.ecmaVersion >= 6 ? "uy" : "") + (parser.options.ecmaVersion >= 9 ? "s" : "") + (parser.options.ecmaVersion >= 13 ? "d" : "") + (parser.options.ecmaVersion >= 15 ? "v" : ""); + this.unicodeProperties = data[parser.options.ecmaVersion >= 14 ? 14 : parser.options.ecmaVersion]; + this.source = ""; + this.flags = ""; + this.start = 0; + this.switchU = false; + this.switchV = false; + this.switchN = false; + this.pos = 0; + this.lastIntValue = 0; + this.lastStringValue = ""; + this.lastAssertionIsQuantifiable = false; + this.numCapturingParens = 0; + this.maxBackReference = 0; + this.groupNames = Object.create(null); + this.backReferenceNames = []; + this.branchID = null; + }; + + RegExpValidationState.prototype.reset = function reset (start, pattern, flags) { + var unicodeSets = flags.indexOf("v") !== -1; + var unicode = flags.indexOf("u") !== -1; + this.start = start | 0; + this.source = pattern + ""; + this.flags = flags; + if (unicodeSets && this.parser.options.ecmaVersion >= 15) { + this.switchU = true; + this.switchV = true; + this.switchN = true; + } else { + this.switchU = unicode && this.parser.options.ecmaVersion >= 6; + this.switchV = false; + this.switchN = unicode && this.parser.options.ecmaVersion >= 9; + } + }; + + RegExpValidationState.prototype.raise = function raise (message) { + this.parser.raiseRecoverable(this.start, ("Invalid regular expression: /" + (this.source) + "/: " + message)); + }; + + // If u flag is given, this returns the code point at the index (it combines a surrogate pair). + // Otherwise, this returns the code unit of the index (can be a part of a surrogate pair). + RegExpValidationState.prototype.at = function at (i, forceU) { + if ( forceU === void 0 ) forceU = false; + + var s = this.source; + var l = s.length; + if (i >= l) { + return -1 + } + var c = s.charCodeAt(i); + if (!(forceU || this.switchU) || c <= 0xD7FF || c >= 0xE000 || i + 1 >= l) { + return c + } + var next = s.charCodeAt(i + 1); + return next >= 0xDC00 && next <= 0xDFFF ? (c << 10) + next - 0x35FDC00 : c + }; + + RegExpValidationState.prototype.nextIndex = function nextIndex (i, forceU) { + if ( forceU === void 0 ) forceU = false; + + var s = this.source; + var l = s.length; + if (i >= l) { + return l + } + var c = s.charCodeAt(i), next; + if (!(forceU || this.switchU) || c <= 0xD7FF || c >= 0xE000 || i + 1 >= l || + (next = s.charCodeAt(i + 1)) < 0xDC00 || next > 0xDFFF) { + return i + 1 + } + return i + 2 + }; + + RegExpValidationState.prototype.current = function current (forceU) { + if ( forceU === void 0 ) forceU = false; + + return this.at(this.pos, forceU) + }; + + RegExpValidationState.prototype.lookahead = function lookahead (forceU) { + if ( forceU === void 0 ) forceU = false; + + return this.at(this.nextIndex(this.pos, forceU), forceU) + }; + + RegExpValidationState.prototype.advance = function advance (forceU) { + if ( forceU === void 0 ) forceU = false; + + this.pos = this.nextIndex(this.pos, forceU); + }; + + RegExpValidationState.prototype.eat = function eat (ch, forceU) { + if ( forceU === void 0 ) forceU = false; + + if (this.current(forceU) === ch) { + this.advance(forceU); + return true + } + return false + }; + + RegExpValidationState.prototype.eatChars = function eatChars (chs, forceU) { + if ( forceU === void 0 ) forceU = false; + + var pos = this.pos; + for (var i = 0, list = chs; i < list.length; i += 1) { + var ch = list[i]; + + var current = this.at(pos, forceU); + if (current === -1 || current !== ch) { + return false + } + pos = this.nextIndex(pos, forceU); + } + this.pos = pos; + return true + }; + + /** + * Validate the flags part of a given RegExpLiteral. + * + * @param {RegExpValidationState} state The state to validate RegExp. + * @returns {void} + */ + pp$1.validateRegExpFlags = function(state) { + var validFlags = state.validFlags; + var flags = state.flags; + + var u = false; + var v = false; + + for (var i = 0; i < flags.length; i++) { + var flag = flags.charAt(i); + if (validFlags.indexOf(flag) === -1) { + this.raise(state.start, "Invalid regular expression flag"); + } + if (flags.indexOf(flag, i + 1) > -1) { + this.raise(state.start, "Duplicate regular expression flag"); + } + if (flag === "u") { u = true; } + if (flag === "v") { v = true; } + } + if (this.options.ecmaVersion >= 15 && u && v) { + this.raise(state.start, "Invalid regular expression flag"); + } + }; + + function hasProp(obj) { + for (var _ in obj) { return true } + return false + } + + /** + * Validate the pattern part of a given RegExpLiteral. + * + * @param {RegExpValidationState} state The state to validate RegExp. + * @returns {void} + */ + pp$1.validateRegExpPattern = function(state) { + this.regexp_pattern(state); + + // The goal symbol for the parse is |Pattern[~U, ~N]|. If the result of + // parsing contains a |GroupName|, reparse with the goal symbol + // |Pattern[~U, +N]| and use this result instead. Throw a *SyntaxError* + // exception if _P_ did not conform to the grammar, if any elements of _P_ + // were not matched by the parse, or if any Early Error conditions exist. + if (!state.switchN && this.options.ecmaVersion >= 9 && hasProp(state.groupNames)) { + state.switchN = true; + this.regexp_pattern(state); + } + }; + + // https://www.ecma-international.org/ecma-262/8.0/#prod-Pattern + pp$1.regexp_pattern = function(state) { + state.pos = 0; + state.lastIntValue = 0; + state.lastStringValue = ""; + state.lastAssertionIsQuantifiable = false; + state.numCapturingParens = 0; + state.maxBackReference = 0; + state.groupNames = Object.create(null); + state.backReferenceNames.length = 0; + state.branchID = null; + + this.regexp_disjunction(state); + + if (state.pos !== state.source.length) { + // Make the same messages as V8. + if (state.eat(0x29 /* ) */)) { + state.raise("Unmatched ')'"); + } + if (state.eat(0x5D /* ] */) || state.eat(0x7D /* } */)) { + state.raise("Lone quantifier brackets"); + } + } + if (state.maxBackReference > state.numCapturingParens) { + state.raise("Invalid escape"); + } + for (var i = 0, list = state.backReferenceNames; i < list.length; i += 1) { + var name = list[i]; + + if (!state.groupNames[name]) { + state.raise("Invalid named capture referenced"); + } + } + }; + + // https://www.ecma-international.org/ecma-262/8.0/#prod-Disjunction + pp$1.regexp_disjunction = function(state) { + var trackDisjunction = this.options.ecmaVersion >= 16; + if (trackDisjunction) { state.branchID = new BranchID(state.branchID, null); } + this.regexp_alternative(state); + while (state.eat(0x7C /* | */)) { + if (trackDisjunction) { state.branchID = state.branchID.sibling(); } + this.regexp_alternative(state); + } + if (trackDisjunction) { state.branchID = state.branchID.parent; } + + // Make the same message as V8. + if (this.regexp_eatQuantifier(state, true)) { + state.raise("Nothing to repeat"); + } + if (state.eat(0x7B /* { */)) { + state.raise("Lone quantifier brackets"); + } + }; + + // https://www.ecma-international.org/ecma-262/8.0/#prod-Alternative + pp$1.regexp_alternative = function(state) { + while (state.pos < state.source.length && this.regexp_eatTerm(state)) {} + }; + + // https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-Term + pp$1.regexp_eatTerm = function(state) { + if (this.regexp_eatAssertion(state)) { + // Handle `QuantifiableAssertion Quantifier` alternative. + // `state.lastAssertionIsQuantifiable` is true if the last eaten Assertion + // is a QuantifiableAssertion. + if (state.lastAssertionIsQuantifiable && this.regexp_eatQuantifier(state)) { + // Make the same message as V8. + if (state.switchU) { + state.raise("Invalid quantifier"); + } + } + return true + } + + if (state.switchU ? this.regexp_eatAtom(state) : this.regexp_eatExtendedAtom(state)) { + this.regexp_eatQuantifier(state); + return true + } + + return false + }; + + // https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-Assertion + pp$1.regexp_eatAssertion = function(state) { + var start = state.pos; + state.lastAssertionIsQuantifiable = false; + + // ^, $ + if (state.eat(0x5E /* ^ */) || state.eat(0x24 /* $ */)) { + return true + } + + // \b \B + if (state.eat(0x5C /* \ */)) { + if (state.eat(0x42 /* B */) || state.eat(0x62 /* b */)) { + return true + } + state.pos = start; + } + + // Lookahead / Lookbehind + if (state.eat(0x28 /* ( */) && state.eat(0x3F /* ? */)) { + var lookbehind = false; + if (this.options.ecmaVersion >= 9) { + lookbehind = state.eat(0x3C /* < */); + } + if (state.eat(0x3D /* = */) || state.eat(0x21 /* ! */)) { + this.regexp_disjunction(state); + if (!state.eat(0x29 /* ) */)) { + state.raise("Unterminated group"); + } + state.lastAssertionIsQuantifiable = !lookbehind; + return true + } + } + + state.pos = start; + return false + }; + + // https://www.ecma-international.org/ecma-262/8.0/#prod-Quantifier + pp$1.regexp_eatQuantifier = function(state, noError) { + if ( noError === void 0 ) noError = false; + + if (this.regexp_eatQuantifierPrefix(state, noError)) { + state.eat(0x3F /* ? */); + return true + } + return false + }; + + // https://www.ecma-international.org/ecma-262/8.0/#prod-QuantifierPrefix + pp$1.regexp_eatQuantifierPrefix = function(state, noError) { + return ( + state.eat(0x2A /* * */) || + state.eat(0x2B /* + */) || + state.eat(0x3F /* ? */) || + this.regexp_eatBracedQuantifier(state, noError) + ) + }; + pp$1.regexp_eatBracedQuantifier = function(state, noError) { + var start = state.pos; + if (state.eat(0x7B /* { */)) { + var min = 0, max = -1; + if (this.regexp_eatDecimalDigits(state)) { + min = state.lastIntValue; + if (state.eat(0x2C /* , */) && this.regexp_eatDecimalDigits(state)) { + max = state.lastIntValue; + } + if (state.eat(0x7D /* } */)) { + // SyntaxError in https://www.ecma-international.org/ecma-262/8.0/#sec-term + if (max !== -1 && max < min && !noError) { + state.raise("numbers out of order in {} quantifier"); + } + return true + } + } + if (state.switchU && !noError) { + state.raise("Incomplete quantifier"); + } + state.pos = start; + } + return false + }; + + // https://www.ecma-international.org/ecma-262/8.0/#prod-Atom + pp$1.regexp_eatAtom = function(state) { + return ( + this.regexp_eatPatternCharacters(state) || + state.eat(0x2E /* . */) || + this.regexp_eatReverseSolidusAtomEscape(state) || + this.regexp_eatCharacterClass(state) || + this.regexp_eatUncapturingGroup(state) || + this.regexp_eatCapturingGroup(state) + ) + }; + pp$1.regexp_eatReverseSolidusAtomEscape = function(state) { + var start = state.pos; + if (state.eat(0x5C /* \ */)) { + if (this.regexp_eatAtomEscape(state)) { + return true + } + state.pos = start; + } + return false + }; + pp$1.regexp_eatUncapturingGroup = function(state) { + var start = state.pos; + if (state.eat(0x28 /* ( */)) { + if (state.eat(0x3F /* ? */)) { + if (this.options.ecmaVersion >= 16) { + var addModifiers = this.regexp_eatModifiers(state); + var hasHyphen = state.eat(0x2D /* - */); + if (addModifiers || hasHyphen) { + for (var i = 0; i < addModifiers.length; i++) { + var modifier = addModifiers.charAt(i); + if (addModifiers.indexOf(modifier, i + 1) > -1) { + state.raise("Duplicate regular expression modifiers"); + } + } + if (hasHyphen) { + var removeModifiers = this.regexp_eatModifiers(state); + if (!addModifiers && !removeModifiers && state.current() === 0x3A /* : */) { + state.raise("Invalid regular expression modifiers"); + } + for (var i$1 = 0; i$1 < removeModifiers.length; i$1++) { + var modifier$1 = removeModifiers.charAt(i$1); + if ( + removeModifiers.indexOf(modifier$1, i$1 + 1) > -1 || + addModifiers.indexOf(modifier$1) > -1 + ) { + state.raise("Duplicate regular expression modifiers"); + } + } + } + } + } + if (state.eat(0x3A /* : */)) { + this.regexp_disjunction(state); + if (state.eat(0x29 /* ) */)) { + return true + } + state.raise("Unterminated group"); + } + } + state.pos = start; + } + return false + }; + pp$1.regexp_eatCapturingGroup = function(state) { + if (state.eat(0x28 /* ( */)) { + if (this.options.ecmaVersion >= 9) { + this.regexp_groupSpecifier(state); + } else if (state.current() === 0x3F /* ? */) { + state.raise("Invalid group"); + } + this.regexp_disjunction(state); + if (state.eat(0x29 /* ) */)) { + state.numCapturingParens += 1; + return true + } + state.raise("Unterminated group"); + } + return false + }; + // RegularExpressionModifiers :: + // [empty] + // RegularExpressionModifiers RegularExpressionModifier + pp$1.regexp_eatModifiers = function(state) { + var modifiers = ""; + var ch = 0; + while ((ch = state.current()) !== -1 && isRegularExpressionModifier(ch)) { + modifiers += codePointToString(ch); + state.advance(); + } + return modifiers + }; + // RegularExpressionModifier :: one of + // `i` `m` `s` + function isRegularExpressionModifier(ch) { + return ch === 0x69 /* i */ || ch === 0x6d /* m */ || ch === 0x73 /* s */ + } + + // https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-ExtendedAtom + pp$1.regexp_eatExtendedAtom = function(state) { + return ( + state.eat(0x2E /* . */) || + this.regexp_eatReverseSolidusAtomEscape(state) || + this.regexp_eatCharacterClass(state) || + this.regexp_eatUncapturingGroup(state) || + this.regexp_eatCapturingGroup(state) || + this.regexp_eatInvalidBracedQuantifier(state) || + this.regexp_eatExtendedPatternCharacter(state) + ) + }; + + // https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-InvalidBracedQuantifier + pp$1.regexp_eatInvalidBracedQuantifier = function(state) { + if (this.regexp_eatBracedQuantifier(state, true)) { + state.raise("Nothing to repeat"); + } + return false + }; + + // https://www.ecma-international.org/ecma-262/8.0/#prod-SyntaxCharacter + pp$1.regexp_eatSyntaxCharacter = function(state) { + var ch = state.current(); + if (isSyntaxCharacter(ch)) { + state.lastIntValue = ch; + state.advance(); + return true + } + return false + }; + function isSyntaxCharacter(ch) { + return ( + ch === 0x24 /* $ */ || + ch >= 0x28 /* ( */ && ch <= 0x2B /* + */ || + ch === 0x2E /* . */ || + ch === 0x3F /* ? */ || + ch >= 0x5B /* [ */ && ch <= 0x5E /* ^ */ || + ch >= 0x7B /* { */ && ch <= 0x7D /* } */ + ) + } + + // https://www.ecma-international.org/ecma-262/8.0/#prod-PatternCharacter + // But eat eager. + pp$1.regexp_eatPatternCharacters = function(state) { + var start = state.pos; + var ch = 0; + while ((ch = state.current()) !== -1 && !isSyntaxCharacter(ch)) { + state.advance(); + } + return state.pos !== start + }; + + // https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-ExtendedPatternCharacter + pp$1.regexp_eatExtendedPatternCharacter = function(state) { + var ch = state.current(); + if ( + ch !== -1 && + ch !== 0x24 /* $ */ && + !(ch >= 0x28 /* ( */ && ch <= 0x2B /* + */) && + ch !== 0x2E /* . */ && + ch !== 0x3F /* ? */ && + ch !== 0x5B /* [ */ && + ch !== 0x5E /* ^ */ && + ch !== 0x7C /* | */ + ) { + state.advance(); + return true + } + return false + }; + + // GroupSpecifier :: + // [empty] + // `?` GroupName + pp$1.regexp_groupSpecifier = function(state) { + if (state.eat(0x3F /* ? */)) { + if (!this.regexp_eatGroupName(state)) { state.raise("Invalid group"); } + var trackDisjunction = this.options.ecmaVersion >= 16; + var known = state.groupNames[state.lastStringValue]; + if (known) { + if (trackDisjunction) { + for (var i = 0, list = known; i < list.length; i += 1) { + var altID = list[i]; + + if (!altID.separatedFrom(state.branchID)) + { state.raise("Duplicate capture group name"); } + } + } else { + state.raise("Duplicate capture group name"); + } + } + if (trackDisjunction) { + (known || (state.groupNames[state.lastStringValue] = [])).push(state.branchID); + } else { + state.groupNames[state.lastStringValue] = true; + } + } + }; + + // GroupName :: + // `<` RegExpIdentifierName `>` + // Note: this updates `state.lastStringValue` property with the eaten name. + pp$1.regexp_eatGroupName = function(state) { + state.lastStringValue = ""; + if (state.eat(0x3C /* < */)) { + if (this.regexp_eatRegExpIdentifierName(state) && state.eat(0x3E /* > */)) { + return true + } + state.raise("Invalid capture group name"); + } + return false + }; + + // RegExpIdentifierName :: + // RegExpIdentifierStart + // RegExpIdentifierName RegExpIdentifierPart + // Note: this updates `state.lastStringValue` property with the eaten name. + pp$1.regexp_eatRegExpIdentifierName = function(state) { + state.lastStringValue = ""; + if (this.regexp_eatRegExpIdentifierStart(state)) { + state.lastStringValue += codePointToString(state.lastIntValue); + while (this.regexp_eatRegExpIdentifierPart(state)) { + state.lastStringValue += codePointToString(state.lastIntValue); + } + return true + } + return false + }; + + // RegExpIdentifierStart :: + // UnicodeIDStart + // `$` + // `_` + // `\` RegExpUnicodeEscapeSequence[+U] + pp$1.regexp_eatRegExpIdentifierStart = function(state) { + var start = state.pos; + var forceU = this.options.ecmaVersion >= 11; + var ch = state.current(forceU); + state.advance(forceU); + + if (ch === 0x5C /* \ */ && this.regexp_eatRegExpUnicodeEscapeSequence(state, forceU)) { + ch = state.lastIntValue; + } + if (isRegExpIdentifierStart(ch)) { + state.lastIntValue = ch; + return true + } + + state.pos = start; + return false + }; + function isRegExpIdentifierStart(ch) { + return isIdentifierStart(ch, true) || ch === 0x24 /* $ */ || ch === 0x5F /* _ */ + } + + // RegExpIdentifierPart :: + // UnicodeIDContinue + // `$` + // `_` + // `\` RegExpUnicodeEscapeSequence[+U] + // + // + pp$1.regexp_eatRegExpIdentifierPart = function(state) { + var start = state.pos; + var forceU = this.options.ecmaVersion >= 11; + var ch = state.current(forceU); + state.advance(forceU); + + if (ch === 0x5C /* \ */ && this.regexp_eatRegExpUnicodeEscapeSequence(state, forceU)) { + ch = state.lastIntValue; + } + if (isRegExpIdentifierPart(ch)) { + state.lastIntValue = ch; + return true + } + + state.pos = start; + return false + }; + function isRegExpIdentifierPart(ch) { + return isIdentifierChar(ch, true) || ch === 0x24 /* $ */ || ch === 0x5F /* _ */ || ch === 0x200C /* */ || ch === 0x200D /* */ + } + + // https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-AtomEscape + pp$1.regexp_eatAtomEscape = function(state) { + if ( + this.regexp_eatBackReference(state) || + this.regexp_eatCharacterClassEscape(state) || + this.regexp_eatCharacterEscape(state) || + (state.switchN && this.regexp_eatKGroupName(state)) + ) { + return true + } + if (state.switchU) { + // Make the same message as V8. + if (state.current() === 0x63 /* c */) { + state.raise("Invalid unicode escape"); + } + state.raise("Invalid escape"); + } + return false + }; + pp$1.regexp_eatBackReference = function(state) { + var start = state.pos; + if (this.regexp_eatDecimalEscape(state)) { + var n = state.lastIntValue; + if (state.switchU) { + // For SyntaxError in https://www.ecma-international.org/ecma-262/8.0/#sec-atomescape + if (n > state.maxBackReference) { + state.maxBackReference = n; + } + return true + } + if (n <= state.numCapturingParens) { + return true + } + state.pos = start; + } + return false + }; + pp$1.regexp_eatKGroupName = function(state) { + if (state.eat(0x6B /* k */)) { + if (this.regexp_eatGroupName(state)) { + state.backReferenceNames.push(state.lastStringValue); + return true + } + state.raise("Invalid named reference"); + } + return false + }; + + // https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-CharacterEscape + pp$1.regexp_eatCharacterEscape = function(state) { + return ( + this.regexp_eatControlEscape(state) || + this.regexp_eatCControlLetter(state) || + this.regexp_eatZero(state) || + this.regexp_eatHexEscapeSequence(state) || + this.regexp_eatRegExpUnicodeEscapeSequence(state, false) || + (!state.switchU && this.regexp_eatLegacyOctalEscapeSequence(state)) || + this.regexp_eatIdentityEscape(state) + ) + }; + pp$1.regexp_eatCControlLetter = function(state) { + var start = state.pos; + if (state.eat(0x63 /* c */)) { + if (this.regexp_eatControlLetter(state)) { + return true + } + state.pos = start; + } + return false + }; + pp$1.regexp_eatZero = function(state) { + if (state.current() === 0x30 /* 0 */ && !isDecimalDigit(state.lookahead())) { + state.lastIntValue = 0; + state.advance(); + return true + } + return false + }; + + // https://www.ecma-international.org/ecma-262/8.0/#prod-ControlEscape + pp$1.regexp_eatControlEscape = function(state) { + var ch = state.current(); + if (ch === 0x74 /* t */) { + state.lastIntValue = 0x09; /* \t */ + state.advance(); + return true + } + if (ch === 0x6E /* n */) { + state.lastIntValue = 0x0A; /* \n */ + state.advance(); + return true + } + if (ch === 0x76 /* v */) { + state.lastIntValue = 0x0B; /* \v */ + state.advance(); + return true + } + if (ch === 0x66 /* f */) { + state.lastIntValue = 0x0C; /* \f */ + state.advance(); + return true + } + if (ch === 0x72 /* r */) { + state.lastIntValue = 0x0D; /* \r */ + state.advance(); + return true + } + return false + }; + + // https://www.ecma-international.org/ecma-262/8.0/#prod-ControlLetter + pp$1.regexp_eatControlLetter = function(state) { + var ch = state.current(); + if (isControlLetter(ch)) { + state.lastIntValue = ch % 0x20; + state.advance(); + return true + } + return false + }; + function isControlLetter(ch) { + return ( + (ch >= 0x41 /* A */ && ch <= 0x5A /* Z */) || + (ch >= 0x61 /* a */ && ch <= 0x7A /* z */) + ) + } + + // https://www.ecma-international.org/ecma-262/8.0/#prod-RegExpUnicodeEscapeSequence + pp$1.regexp_eatRegExpUnicodeEscapeSequence = function(state, forceU) { + if ( forceU === void 0 ) forceU = false; + + var start = state.pos; + var switchU = forceU || state.switchU; + + if (state.eat(0x75 /* u */)) { + if (this.regexp_eatFixedHexDigits(state, 4)) { + var lead = state.lastIntValue; + if (switchU && lead >= 0xD800 && lead <= 0xDBFF) { + var leadSurrogateEnd = state.pos; + if (state.eat(0x5C /* \ */) && state.eat(0x75 /* u */) && this.regexp_eatFixedHexDigits(state, 4)) { + var trail = state.lastIntValue; + if (trail >= 0xDC00 && trail <= 0xDFFF) { + state.lastIntValue = (lead - 0xD800) * 0x400 + (trail - 0xDC00) + 0x10000; + return true + } + } + state.pos = leadSurrogateEnd; + state.lastIntValue = lead; + } + return true + } + if ( + switchU && + state.eat(0x7B /* { */) && + this.regexp_eatHexDigits(state) && + state.eat(0x7D /* } */) && + isValidUnicode(state.lastIntValue) + ) { + return true + } + if (switchU) { + state.raise("Invalid unicode escape"); + } + state.pos = start; + } + + return false + }; + function isValidUnicode(ch) { + return ch >= 0 && ch <= 0x10FFFF + } + + // https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-IdentityEscape + pp$1.regexp_eatIdentityEscape = function(state) { + if (state.switchU) { + if (this.regexp_eatSyntaxCharacter(state)) { + return true + } + if (state.eat(0x2F /* / */)) { + state.lastIntValue = 0x2F; /* / */ + return true + } + return false + } + + var ch = state.current(); + if (ch !== 0x63 /* c */ && (!state.switchN || ch !== 0x6B /* k */)) { + state.lastIntValue = ch; + state.advance(); + return true + } + + return false + }; + + // https://www.ecma-international.org/ecma-262/8.0/#prod-DecimalEscape + pp$1.regexp_eatDecimalEscape = function(state) { + state.lastIntValue = 0; + var ch = state.current(); + if (ch >= 0x31 /* 1 */ && ch <= 0x39 /* 9 */) { + do { + state.lastIntValue = 10 * state.lastIntValue + (ch - 0x30 /* 0 */); + state.advance(); + } while ((ch = state.current()) >= 0x30 /* 0 */ && ch <= 0x39 /* 9 */) + return true + } + return false + }; + + // Return values used by character set parsing methods, needed to + // forbid negation of sets that can match strings. + var CharSetNone = 0; // Nothing parsed + var CharSetOk = 1; // Construct parsed, cannot contain strings + var CharSetString = 2; // Construct parsed, can contain strings + + // https://www.ecma-international.org/ecma-262/8.0/#prod-CharacterClassEscape + pp$1.regexp_eatCharacterClassEscape = function(state) { + var ch = state.current(); + + if (isCharacterClassEscape(ch)) { + state.lastIntValue = -1; + state.advance(); + return CharSetOk + } + + var negate = false; + if ( + state.switchU && + this.options.ecmaVersion >= 9 && + ((negate = ch === 0x50 /* P */) || ch === 0x70 /* p */) + ) { + state.lastIntValue = -1; + state.advance(); + var result; + if ( + state.eat(0x7B /* { */) && + (result = this.regexp_eatUnicodePropertyValueExpression(state)) && + state.eat(0x7D /* } */) + ) { + if (negate && result === CharSetString) { state.raise("Invalid property name"); } + return result + } + state.raise("Invalid property name"); + } + + return CharSetNone + }; + + function isCharacterClassEscape(ch) { + return ( + ch === 0x64 /* d */ || + ch === 0x44 /* D */ || + ch === 0x73 /* s */ || + ch === 0x53 /* S */ || + ch === 0x77 /* w */ || + ch === 0x57 /* W */ + ) + } + + // UnicodePropertyValueExpression :: + // UnicodePropertyName `=` UnicodePropertyValue + // LoneUnicodePropertyNameOrValue + pp$1.regexp_eatUnicodePropertyValueExpression = function(state) { + var start = state.pos; + + // UnicodePropertyName `=` UnicodePropertyValue + if (this.regexp_eatUnicodePropertyName(state) && state.eat(0x3D /* = */)) { + var name = state.lastStringValue; + if (this.regexp_eatUnicodePropertyValue(state)) { + var value = state.lastStringValue; + this.regexp_validateUnicodePropertyNameAndValue(state, name, value); + return CharSetOk + } + } + state.pos = start; + + // LoneUnicodePropertyNameOrValue + if (this.regexp_eatLoneUnicodePropertyNameOrValue(state)) { + var nameOrValue = state.lastStringValue; + return this.regexp_validateUnicodePropertyNameOrValue(state, nameOrValue) + } + return CharSetNone + }; + + pp$1.regexp_validateUnicodePropertyNameAndValue = function(state, name, value) { + if (!hasOwn(state.unicodeProperties.nonBinary, name)) + { state.raise("Invalid property name"); } + if (!state.unicodeProperties.nonBinary[name].test(value)) + { state.raise("Invalid property value"); } + }; + + pp$1.regexp_validateUnicodePropertyNameOrValue = function(state, nameOrValue) { + if (state.unicodeProperties.binary.test(nameOrValue)) { return CharSetOk } + if (state.switchV && state.unicodeProperties.binaryOfStrings.test(nameOrValue)) { return CharSetString } + state.raise("Invalid property name"); + }; + + // UnicodePropertyName :: + // UnicodePropertyNameCharacters + pp$1.regexp_eatUnicodePropertyName = function(state) { + var ch = 0; + state.lastStringValue = ""; + while (isUnicodePropertyNameCharacter(ch = state.current())) { + state.lastStringValue += codePointToString(ch); + state.advance(); + } + return state.lastStringValue !== "" + }; + + function isUnicodePropertyNameCharacter(ch) { + return isControlLetter(ch) || ch === 0x5F /* _ */ + } + + // UnicodePropertyValue :: + // UnicodePropertyValueCharacters + pp$1.regexp_eatUnicodePropertyValue = function(state) { + var ch = 0; + state.lastStringValue = ""; + while (isUnicodePropertyValueCharacter(ch = state.current())) { + state.lastStringValue += codePointToString(ch); + state.advance(); + } + return state.lastStringValue !== "" + }; + function isUnicodePropertyValueCharacter(ch) { + return isUnicodePropertyNameCharacter(ch) || isDecimalDigit(ch) + } + + // LoneUnicodePropertyNameOrValue :: + // UnicodePropertyValueCharacters + pp$1.regexp_eatLoneUnicodePropertyNameOrValue = function(state) { + return this.regexp_eatUnicodePropertyValue(state) + }; + + // https://www.ecma-international.org/ecma-262/8.0/#prod-CharacterClass + pp$1.regexp_eatCharacterClass = function(state) { + if (state.eat(0x5B /* [ */)) { + var negate = state.eat(0x5E /* ^ */); + var result = this.regexp_classContents(state); + if (!state.eat(0x5D /* ] */)) + { state.raise("Unterminated character class"); } + if (negate && result === CharSetString) + { state.raise("Negated character class may contain strings"); } + return true + } + return false + }; + + // https://tc39.es/ecma262/#prod-ClassContents + // https://www.ecma-international.org/ecma-262/8.0/#prod-ClassRanges + pp$1.regexp_classContents = function(state) { + if (state.current() === 0x5D /* ] */) { return CharSetOk } + if (state.switchV) { return this.regexp_classSetExpression(state) } + this.regexp_nonEmptyClassRanges(state); + return CharSetOk + }; + + // https://www.ecma-international.org/ecma-262/8.0/#prod-NonemptyClassRanges + // https://www.ecma-international.org/ecma-262/8.0/#prod-NonemptyClassRangesNoDash + pp$1.regexp_nonEmptyClassRanges = function(state) { + while (this.regexp_eatClassAtom(state)) { + var left = state.lastIntValue; + if (state.eat(0x2D /* - */) && this.regexp_eatClassAtom(state)) { + var right = state.lastIntValue; + if (state.switchU && (left === -1 || right === -1)) { + state.raise("Invalid character class"); + } + if (left !== -1 && right !== -1 && left > right) { + state.raise("Range out of order in character class"); + } + } + } + }; + + // https://www.ecma-international.org/ecma-262/8.0/#prod-ClassAtom + // https://www.ecma-international.org/ecma-262/8.0/#prod-ClassAtomNoDash + pp$1.regexp_eatClassAtom = function(state) { + var start = state.pos; + + if (state.eat(0x5C /* \ */)) { + if (this.regexp_eatClassEscape(state)) { + return true + } + if (state.switchU) { + // Make the same message as V8. + var ch$1 = state.current(); + if (ch$1 === 0x63 /* c */ || isOctalDigit(ch$1)) { + state.raise("Invalid class escape"); + } + state.raise("Invalid escape"); + } + state.pos = start; + } + + var ch = state.current(); + if (ch !== 0x5D /* ] */) { + state.lastIntValue = ch; + state.advance(); + return true + } + + return false + }; + + // https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-ClassEscape + pp$1.regexp_eatClassEscape = function(state) { + var start = state.pos; + + if (state.eat(0x62 /* b */)) { + state.lastIntValue = 0x08; /* */ + return true + } + + if (state.switchU && state.eat(0x2D /* - */)) { + state.lastIntValue = 0x2D; /* - */ + return true + } + + if (!state.switchU && state.eat(0x63 /* c */)) { + if (this.regexp_eatClassControlLetter(state)) { + return true + } + state.pos = start; + } + + return ( + this.regexp_eatCharacterClassEscape(state) || + this.regexp_eatCharacterEscape(state) + ) + }; + + // https://tc39.es/ecma262/#prod-ClassSetExpression + // https://tc39.es/ecma262/#prod-ClassUnion + // https://tc39.es/ecma262/#prod-ClassIntersection + // https://tc39.es/ecma262/#prod-ClassSubtraction + pp$1.regexp_classSetExpression = function(state) { + var result = CharSetOk, subResult; + if (this.regexp_eatClassSetRange(state)) ; else if (subResult = this.regexp_eatClassSetOperand(state)) { + if (subResult === CharSetString) { result = CharSetString; } + // https://tc39.es/ecma262/#prod-ClassIntersection + var start = state.pos; + while (state.eatChars([0x26, 0x26] /* && */)) { + if ( + state.current() !== 0x26 /* & */ && + (subResult = this.regexp_eatClassSetOperand(state)) + ) { + if (subResult !== CharSetString) { result = CharSetOk; } + continue + } + state.raise("Invalid character in character class"); + } + if (start !== state.pos) { return result } + // https://tc39.es/ecma262/#prod-ClassSubtraction + while (state.eatChars([0x2D, 0x2D] /* -- */)) { + if (this.regexp_eatClassSetOperand(state)) { continue } + state.raise("Invalid character in character class"); + } + if (start !== state.pos) { return result } + } else { + state.raise("Invalid character in character class"); + } + // https://tc39.es/ecma262/#prod-ClassUnion + for (;;) { + if (this.regexp_eatClassSetRange(state)) { continue } + subResult = this.regexp_eatClassSetOperand(state); + if (!subResult) { return result } + if (subResult === CharSetString) { result = CharSetString; } + } + }; + + // https://tc39.es/ecma262/#prod-ClassSetRange + pp$1.regexp_eatClassSetRange = function(state) { + var start = state.pos; + if (this.regexp_eatClassSetCharacter(state)) { + var left = state.lastIntValue; + if (state.eat(0x2D /* - */) && this.regexp_eatClassSetCharacter(state)) { + var right = state.lastIntValue; + if (left !== -1 && right !== -1 && left > right) { + state.raise("Range out of order in character class"); + } + return true + } + state.pos = start; + } + return false + }; + + // https://tc39.es/ecma262/#prod-ClassSetOperand + pp$1.regexp_eatClassSetOperand = function(state) { + if (this.regexp_eatClassSetCharacter(state)) { return CharSetOk } + return this.regexp_eatClassStringDisjunction(state) || this.regexp_eatNestedClass(state) + }; + + // https://tc39.es/ecma262/#prod-NestedClass + pp$1.regexp_eatNestedClass = function(state) { + var start = state.pos; + if (state.eat(0x5B /* [ */)) { + var negate = state.eat(0x5E /* ^ */); + var result = this.regexp_classContents(state); + if (state.eat(0x5D /* ] */)) { + if (negate && result === CharSetString) { + state.raise("Negated character class may contain strings"); + } + return result + } + state.pos = start; + } + if (state.eat(0x5C /* \ */)) { + var result$1 = this.regexp_eatCharacterClassEscape(state); + if (result$1) { + return result$1 + } + state.pos = start; + } + return null + }; + + // https://tc39.es/ecma262/#prod-ClassStringDisjunction + pp$1.regexp_eatClassStringDisjunction = function(state) { + var start = state.pos; + if (state.eatChars([0x5C, 0x71] /* \q */)) { + if (state.eat(0x7B /* { */)) { + var result = this.regexp_classStringDisjunctionContents(state); + if (state.eat(0x7D /* } */)) { + return result + } + } else { + // Make the same message as V8. + state.raise("Invalid escape"); + } + state.pos = start; + } + return null + }; + + // https://tc39.es/ecma262/#prod-ClassStringDisjunctionContents + pp$1.regexp_classStringDisjunctionContents = function(state) { + var result = this.regexp_classString(state); + while (state.eat(0x7C /* | */)) { + if (this.regexp_classString(state) === CharSetString) { result = CharSetString; } + } + return result + }; + + // https://tc39.es/ecma262/#prod-ClassString + // https://tc39.es/ecma262/#prod-NonEmptyClassString + pp$1.regexp_classString = function(state) { + var count = 0; + while (this.regexp_eatClassSetCharacter(state)) { count++; } + return count === 1 ? CharSetOk : CharSetString + }; + + // https://tc39.es/ecma262/#prod-ClassSetCharacter + pp$1.regexp_eatClassSetCharacter = function(state) { + var start = state.pos; + if (state.eat(0x5C /* \ */)) { + if ( + this.regexp_eatCharacterEscape(state) || + this.regexp_eatClassSetReservedPunctuator(state) + ) { + return true + } + if (state.eat(0x62 /* b */)) { + state.lastIntValue = 0x08; /* */ + return true + } + state.pos = start; + return false + } + var ch = state.current(); + if (ch < 0 || ch === state.lookahead() && isClassSetReservedDoublePunctuatorCharacter(ch)) { return false } + if (isClassSetSyntaxCharacter(ch)) { return false } + state.advance(); + state.lastIntValue = ch; + return true + }; + + // https://tc39.es/ecma262/#prod-ClassSetReservedDoublePunctuator + function isClassSetReservedDoublePunctuatorCharacter(ch) { + return ( + ch === 0x21 /* ! */ || + ch >= 0x23 /* # */ && ch <= 0x26 /* & */ || + ch >= 0x2A /* * */ && ch <= 0x2C /* , */ || + ch === 0x2E /* . */ || + ch >= 0x3A /* : */ && ch <= 0x40 /* @ */ || + ch === 0x5E /* ^ */ || + ch === 0x60 /* ` */ || + ch === 0x7E /* ~ */ + ) + } + + // https://tc39.es/ecma262/#prod-ClassSetSyntaxCharacter + function isClassSetSyntaxCharacter(ch) { + return ( + ch === 0x28 /* ( */ || + ch === 0x29 /* ) */ || + ch === 0x2D /* - */ || + ch === 0x2F /* / */ || + ch >= 0x5B /* [ */ && ch <= 0x5D /* ] */ || + ch >= 0x7B /* { */ && ch <= 0x7D /* } */ + ) + } + + // https://tc39.es/ecma262/#prod-ClassSetReservedPunctuator + pp$1.regexp_eatClassSetReservedPunctuator = function(state) { + var ch = state.current(); + if (isClassSetReservedPunctuator(ch)) { + state.lastIntValue = ch; + state.advance(); + return true + } + return false + }; + + // https://tc39.es/ecma262/#prod-ClassSetReservedPunctuator + function isClassSetReservedPunctuator(ch) { + return ( + ch === 0x21 /* ! */ || + ch === 0x23 /* # */ || + ch === 0x25 /* % */ || + ch === 0x26 /* & */ || + ch === 0x2C /* , */ || + ch === 0x2D /* - */ || + ch >= 0x3A /* : */ && ch <= 0x3E /* > */ || + ch === 0x40 /* @ */ || + ch === 0x60 /* ` */ || + ch === 0x7E /* ~ */ + ) + } + + // https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-ClassControlLetter + pp$1.regexp_eatClassControlLetter = function(state) { + var ch = state.current(); + if (isDecimalDigit(ch) || ch === 0x5F /* _ */) { + state.lastIntValue = ch % 0x20; + state.advance(); + return true + } + return false + }; + + // https://www.ecma-international.org/ecma-262/8.0/#prod-HexEscapeSequence + pp$1.regexp_eatHexEscapeSequence = function(state) { + var start = state.pos; + if (state.eat(0x78 /* x */)) { + if (this.regexp_eatFixedHexDigits(state, 2)) { + return true + } + if (state.switchU) { + state.raise("Invalid escape"); + } + state.pos = start; + } + return false + }; + + // https://www.ecma-international.org/ecma-262/8.0/#prod-DecimalDigits + pp$1.regexp_eatDecimalDigits = function(state) { + var start = state.pos; + var ch = 0; + state.lastIntValue = 0; + while (isDecimalDigit(ch = state.current())) { + state.lastIntValue = 10 * state.lastIntValue + (ch - 0x30 /* 0 */); + state.advance(); + } + return state.pos !== start + }; + function isDecimalDigit(ch) { + return ch >= 0x30 /* 0 */ && ch <= 0x39 /* 9 */ + } + + // https://www.ecma-international.org/ecma-262/8.0/#prod-HexDigits + pp$1.regexp_eatHexDigits = function(state) { + var start = state.pos; + var ch = 0; + state.lastIntValue = 0; + while (isHexDigit(ch = state.current())) { + state.lastIntValue = 16 * state.lastIntValue + hexToInt(ch); + state.advance(); + } + return state.pos !== start + }; + function isHexDigit(ch) { + return ( + (ch >= 0x30 /* 0 */ && ch <= 0x39 /* 9 */) || + (ch >= 0x41 /* A */ && ch <= 0x46 /* F */) || + (ch >= 0x61 /* a */ && ch <= 0x66 /* f */) + ) + } + function hexToInt(ch) { + if (ch >= 0x41 /* A */ && ch <= 0x46 /* F */) { + return 10 + (ch - 0x41 /* A */) + } + if (ch >= 0x61 /* a */ && ch <= 0x66 /* f */) { + return 10 + (ch - 0x61 /* a */) + } + return ch - 0x30 /* 0 */ + } + + // https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-LegacyOctalEscapeSequence + // Allows only 0-377(octal) i.e. 0-255(decimal). + pp$1.regexp_eatLegacyOctalEscapeSequence = function(state) { + if (this.regexp_eatOctalDigit(state)) { + var n1 = state.lastIntValue; + if (this.regexp_eatOctalDigit(state)) { + var n2 = state.lastIntValue; + if (n1 <= 3 && this.regexp_eatOctalDigit(state)) { + state.lastIntValue = n1 * 64 + n2 * 8 + state.lastIntValue; + } else { + state.lastIntValue = n1 * 8 + n2; + } + } else { + state.lastIntValue = n1; + } + return true + } + return false + }; + + // https://www.ecma-international.org/ecma-262/8.0/#prod-OctalDigit + pp$1.regexp_eatOctalDigit = function(state) { + var ch = state.current(); + if (isOctalDigit(ch)) { + state.lastIntValue = ch - 0x30; /* 0 */ + state.advance(); + return true + } + state.lastIntValue = 0; + return false + }; + function isOctalDigit(ch) { + return ch >= 0x30 /* 0 */ && ch <= 0x37 /* 7 */ + } + + // https://www.ecma-international.org/ecma-262/8.0/#prod-Hex4Digits + // https://www.ecma-international.org/ecma-262/8.0/#prod-HexDigit + // And HexDigit HexDigit in https://www.ecma-international.org/ecma-262/8.0/#prod-HexEscapeSequence + pp$1.regexp_eatFixedHexDigits = function(state, length) { + var start = state.pos; + state.lastIntValue = 0; + for (var i = 0; i < length; ++i) { + var ch = state.current(); + if (!isHexDigit(ch)) { + state.pos = start; + return false + } + state.lastIntValue = 16 * state.lastIntValue + hexToInt(ch); + state.advance(); + } + return true + }; + + // Object type used to represent tokens. Note that normally, tokens + // simply exist as properties on the parser object. This is only + // used for the onToken callback and the external tokenizer. + + var Token = function Token(p) { + this.type = p.type; + this.value = p.value; + this.start = p.start; + this.end = p.end; + if (p.options.locations) + { this.loc = new SourceLocation(p, p.startLoc, p.endLoc); } + if (p.options.ranges) + { this.range = [p.start, p.end]; } + }; + + // ## Tokenizer + + var pp = Parser.prototype; + + // Move to the next token + + pp.next = function(ignoreEscapeSequenceInKeyword) { + if (!ignoreEscapeSequenceInKeyword && this.type.keyword && this.containsEsc) + { this.raiseRecoverable(this.start, "Escape sequence in keyword " + this.type.keyword); } + if (this.options.onToken) + { this.options.onToken(new Token(this)); } + + this.lastTokEnd = this.end; + this.lastTokStart = this.start; + this.lastTokEndLoc = this.endLoc; + this.lastTokStartLoc = this.startLoc; + this.nextToken(); + }; + + pp.getToken = function() { + this.next(); + return new Token(this) + }; + + // If we're in an ES6 environment, make parsers iterable + if (typeof Symbol !== "undefined") + { pp[Symbol.iterator] = function() { + var this$1$1 = this; + + return { + next: function () { + var token = this$1$1.getToken(); + return { + done: token.type === types$1.eof, + value: token + } + } + } + }; } + + // Toggle strict mode. Re-reads the next number or string to please + // pedantic tests (`"use strict"; 010;` should fail). + + // Read a single token, updating the parser object's token-related + // properties. + + pp.nextToken = function() { + var curContext = this.curContext(); + if (!curContext || !curContext.preserveSpace) { this.skipSpace(); } + + this.start = this.pos; + if (this.options.locations) { this.startLoc = this.curPosition(); } + if (this.pos >= this.input.length) { return this.finishToken(types$1.eof) } + + if (curContext.override) { return curContext.override(this) } + else { this.readToken(this.fullCharCodeAtPos()); } + }; + + pp.readToken = function(code) { + // Identifier or keyword. '\uXXXX' sequences are allowed in + // identifiers, so '\' also dispatches to that. + if (isIdentifierStart(code, this.options.ecmaVersion >= 6) || code === 92 /* '\' */) + { return this.readWord() } + + return this.getTokenFromCode(code) + }; + + pp.fullCharCodeAt = function(pos) { + var code = this.input.charCodeAt(pos); + if (code <= 0xd7ff || code >= 0xdc00) { return code } + var next = this.input.charCodeAt(pos + 1); + return next <= 0xdbff || next >= 0xe000 ? code : (code << 10) + next - 0x35fdc00 + }; + + pp.fullCharCodeAtPos = function() { + return this.fullCharCodeAt(this.pos) + }; + + pp.skipBlockComment = function() { + var startLoc = this.options.onComment && this.curPosition(); + var start = this.pos, end = this.input.indexOf("*/", this.pos += 2); + if (end === -1) { this.raise(this.pos - 2, "Unterminated comment"); } + this.pos = end + 2; + if (this.options.locations) { + for (var nextBreak = (void 0), pos = start; (nextBreak = nextLineBreak(this.input, pos, this.pos)) > -1;) { + ++this.curLine; + pos = this.lineStart = nextBreak; + } + } + if (this.options.onComment) + { this.options.onComment(true, this.input.slice(start + 2, end), start, this.pos, + startLoc, this.curPosition()); } + }; + + pp.skipLineComment = function(startSkip) { + var start = this.pos; + var startLoc = this.options.onComment && this.curPosition(); + var ch = this.input.charCodeAt(this.pos += startSkip); + while (this.pos < this.input.length && !isNewLine(ch)) { + ch = this.input.charCodeAt(++this.pos); + } + if (this.options.onComment) + { this.options.onComment(false, this.input.slice(start + startSkip, this.pos), start, this.pos, + startLoc, this.curPosition()); } + }; + + // Called at the start of the parse and after every token. Skips + // whitespace and comments, and. + + pp.skipSpace = function() { + loop: while (this.pos < this.input.length) { + var ch = this.input.charCodeAt(this.pos); + switch (ch) { + case 32: case 160: // ' ' + ++this.pos; + break + case 13: + if (this.input.charCodeAt(this.pos + 1) === 10) { + ++this.pos; + } + case 10: case 8232: case 8233: + ++this.pos; + if (this.options.locations) { + ++this.curLine; + this.lineStart = this.pos; + } + break + case 47: // '/' + switch (this.input.charCodeAt(this.pos + 1)) { + case 42: // '*' + this.skipBlockComment(); + break + case 47: + this.skipLineComment(2); + break + default: + break loop + } + break + default: + if (ch > 8 && ch < 14 || ch >= 5760 && nonASCIIwhitespace.test(String.fromCharCode(ch))) { + ++this.pos; + } else { + break loop + } + } + } + }; + + // Called at the end of every token. Sets `end`, `val`, and + // maintains `context` and `exprAllowed`, and skips the space after + // the token, so that the next one's `start` will point at the + // right position. + + pp.finishToken = function(type, val) { + this.end = this.pos; + if (this.options.locations) { this.endLoc = this.curPosition(); } + var prevType = this.type; + this.type = type; + this.value = val; + + this.updateContext(prevType); + }; + + // ### Token reading + + // This is the function that is called to fetch the next token. It + // is somewhat obscure, because it works in character codes rather + // than characters, and because operator parsing has been inlined + // into it. + // + // All in the name of speed. + // + pp.readToken_dot = function() { + var next = this.input.charCodeAt(this.pos + 1); + if (next >= 48 && next <= 57) { return this.readNumber(true) } + var next2 = this.input.charCodeAt(this.pos + 2); + if (this.options.ecmaVersion >= 6 && next === 46 && next2 === 46) { // 46 = dot '.' + this.pos += 3; + return this.finishToken(types$1.ellipsis) + } else { + ++this.pos; + return this.finishToken(types$1.dot) + } + }; + + pp.readToken_slash = function() { // '/' + var next = this.input.charCodeAt(this.pos + 1); + if (this.exprAllowed) { ++this.pos; return this.readRegexp() } + if (next === 61) { return this.finishOp(types$1.assign, 2) } + return this.finishOp(types$1.slash, 1) + }; + + pp.readToken_mult_modulo_exp = function(code) { // '%*' + var next = this.input.charCodeAt(this.pos + 1); + var size = 1; + var tokentype = code === 42 ? types$1.star : types$1.modulo; + + // exponentiation operator ** and **= + if (this.options.ecmaVersion >= 7 && code === 42 && next === 42) { + ++size; + tokentype = types$1.starstar; + next = this.input.charCodeAt(this.pos + 2); + } + + if (next === 61) { return this.finishOp(types$1.assign, size + 1) } + return this.finishOp(tokentype, size) + }; + + pp.readToken_pipe_amp = function(code) { // '|&' + var next = this.input.charCodeAt(this.pos + 1); + if (next === code) { + if (this.options.ecmaVersion >= 12) { + var next2 = this.input.charCodeAt(this.pos + 2); + if (next2 === 61) { return this.finishOp(types$1.assign, 3) } + } + return this.finishOp(code === 124 ? types$1.logicalOR : types$1.logicalAND, 2) + } + if (next === 61) { return this.finishOp(types$1.assign, 2) } + return this.finishOp(code === 124 ? types$1.bitwiseOR : types$1.bitwiseAND, 1) + }; + + pp.readToken_caret = function() { // '^' + var next = this.input.charCodeAt(this.pos + 1); + if (next === 61) { return this.finishOp(types$1.assign, 2) } + return this.finishOp(types$1.bitwiseXOR, 1) + }; + + pp.readToken_plus_min = function(code) { // '+-' + var next = this.input.charCodeAt(this.pos + 1); + if (next === code) { + if (next === 45 && !this.inModule && this.input.charCodeAt(this.pos + 2) === 62 && + (this.lastTokEnd === 0 || lineBreak.test(this.input.slice(this.lastTokEnd, this.pos)))) { + // A `-->` line comment + this.skipLineComment(3); + this.skipSpace(); + return this.nextToken() + } + return this.finishOp(types$1.incDec, 2) + } + if (next === 61) { return this.finishOp(types$1.assign, 2) } + return this.finishOp(types$1.plusMin, 1) + }; + + pp.readToken_lt_gt = function(code) { // '<>' + var next = this.input.charCodeAt(this.pos + 1); + var size = 1; + if (next === code) { + size = code === 62 && this.input.charCodeAt(this.pos + 2) === 62 ? 3 : 2; + if (this.input.charCodeAt(this.pos + size) === 61) { return this.finishOp(types$1.assign, size + 1) } + return this.finishOp(types$1.bitShift, size) + } + if (next === 33 && code === 60 && !this.inModule && this.input.charCodeAt(this.pos + 2) === 45 && + this.input.charCodeAt(this.pos + 3) === 45) { + // `` line comment + this.skipLineComment(3); + this.skipSpace(); + return this.nextToken() + } + return this.finishOp(types$1.incDec, 2) + } + if (next === 61) { return this.finishOp(types$1.assign, 2) } + return this.finishOp(types$1.plusMin, 1) +}; + +pp.readToken_lt_gt = function(code) { // '<>' + var next = this.input.charCodeAt(this.pos + 1); + var size = 1; + if (next === code) { + size = code === 62 && this.input.charCodeAt(this.pos + 2) === 62 ? 3 : 2; + if (this.input.charCodeAt(this.pos + size) === 61) { return this.finishOp(types$1.assign, size + 1) } + return this.finishOp(types$1.bitShift, size) + } + if (next === 33 && code === 60 && !this.inModule && this.input.charCodeAt(this.pos + 2) === 45 && + this.input.charCodeAt(this.pos + 3) === 45) { + // `)/],[PR.PR_LITERAL,/^(?:\d+|\d*\.\d+)(?:%|[a-z]+)?/i],[PR.PR_LITERAL,/^#(?:[0-9a-f]{3}){1,2}/i],[PR.PR_PLAIN,/^-?(?:[_a-z]|(?:\\[\da-f]+ ?))(?:[_a-z\d\-]|\\(?:\\[\da-f]+ ?))*/i],[PR.PR_PUNCTUATION,/^[^\s\w\'\"]+/]]),["css"]);PR.registerLangHandler(PR.createSimpleLexer([],[[PR.PR_KEYWORD,/^-?(?:[_a-z]|(?:\\[\da-f]+ ?))(?:[_a-z\d\-]|\\(?:\\[\da-f]+ ?))*/i]]),["css-kw"]);PR.registerLangHandler(PR.createSimpleLexer([],[[PR.PR_STRING,/^[^\)\"\']+/]]),["css-str"]); diff --git a/node_modules/istanbul-reports/lib/html/index.js b/node_modules/istanbul-reports/lib/html/index.js new file mode 100644 index 0000000..2d7f7be --- /dev/null +++ b/node_modules/istanbul-reports/lib/html/index.js @@ -0,0 +1,421 @@ +'use strict'; +/* + Copyright 2012-2015, Yahoo Inc. + Copyrights licensed under the New BSD License. See the accompanying LICENSE file for terms. + */ +const fs = require('fs'); +const path = require('path'); +const html = require('html-escaper'); +const { ReportBase } = require('istanbul-lib-report'); +const annotator = require('./annotator'); + +function htmlHead(details) { + return ` + + Code coverage report for ${html.escape(details.entity)} + + + + + + + + `; +} + +function headerTemplate(details) { + function metricsTemplate({ pct, covered, total }, kind) { + return ` +
+ ${pct}% + ${kind} + ${covered}/${total} +
+ `; + } + + function skipTemplate(metrics) { + const statements = metrics.statements.skipped; + const branches = metrics.branches.skipped; + const functions = metrics.functions.skipped; + + const countLabel = (c, label, plural) => + c === 0 ? [] : `${c} ${label}${c === 1 ? '' : plural}`; + const skips = [].concat( + countLabel(statements, 'statement', 's'), + countLabel(functions, 'function', 's'), + countLabel(branches, 'branch', 'es') + ); + + if (skips.length === 0) { + return ''; + } + + return ` +
+ ${skips.join(', ')} + Ignored      +
+ `; + } + + return ` + + +${htmlHead(details)} + +
+
+

${details.pathHtml}

+
+ ${metricsTemplate(details.metrics.statements, 'Statements')} + ${metricsTemplate(details.metrics.branches, 'Branches')} + ${metricsTemplate(details.metrics.functions, 'Functions')} + ${metricsTemplate(details.metrics.lines, 'Lines')} + ${skipTemplate(details.metrics)} +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+ `; +} + +function footerTemplate(details) { + return ` +
+
+ + + + + + + + `; +} + +function detailTemplate(data) { + const lineNumbers = new Array(data.maxLines).fill().map((_, i) => i + 1); + const lineLink = num => + `${num}`; + const lineCount = line => + `${line.hits}`; + + /* This is rendered in a `
`, need control of all whitespace. */
+    return [
+        '',
+        `${lineNumbers
+            .map(lineLink)
+            .join('\n')}`,
+        `${data.lineCoverage
+            .map(lineCount)
+            .join('\n')}`,
+        `
${data.annotatedCode.join(
+            '\n'
+        )}
`, + '' + ].join(''); +} +const summaryTableHeader = [ + '
', + '', + '', + '', + ' ', + ' ', + ' ', + ' ', + ' ', + ' ', + ' ', + ' ', + ' ', + ' ', + '', + '', + '' +].join('\n'); + +function summaryLineTemplate(details) { + const { reportClasses, metrics, file, output } = details; + const percentGraph = pct => { + if (!isFinite(pct)) { + return ''; + } + + const cls = ['cover-fill']; + if (pct === 100) { + cls.push('cover-full'); + } + + pct = Math.floor(pct); + return [ + `
`, + `
` + ].join(''); + }; + const summaryType = (type, showGraph = false) => { + const info = metrics[type]; + const reportClass = reportClasses[type]; + const result = [ + ``, + `` + ]; + if (showGraph) { + result.unshift( + `` + ); + } + + return result; + }; + + return [] + .concat( + '', + ``, + summaryType('statements', true), + summaryType('branches'), + summaryType('functions'), + summaryType('lines'), + '\n' + ) + .join('\n\t'); +} + +const summaryTableFooter = ['', '
FileStatementsBranchesFunctionsLines
${info.pct}%${info.covered}/${info.total}`, + `
${percentGraph(info.pct)}
`, + `
${html.escape(file)}
', '
'].join('\n'); +const emptyClasses = { + statements: 'empty', + lines: 'empty', + functions: 'empty', + branches: 'empty' +}; + +const standardLinkMapper = { + getPath(node) { + if (typeof node === 'string') { + return node; + } + let filePath = node.getQualifiedName(); + if (node.isSummary()) { + if (filePath !== '') { + filePath += '/index.html'; + } else { + filePath = 'index.html'; + } + } else { + filePath += '.html'; + } + return filePath; + }, + + relativePath(source, target) { + const targetPath = this.getPath(target); + const sourcePath = path.dirname(this.getPath(source)); + return path.posix.relative(sourcePath, targetPath); + }, + + assetPath(node, name) { + return this.relativePath(this.getPath(node), name); + } +}; + +function fixPct(metrics) { + Object.keys(emptyClasses).forEach(key => { + metrics[key].pct = 0; + }); + return metrics; +} + +class HtmlReport extends ReportBase { + constructor(opts) { + super(); + + this.verbose = opts.verbose; + this.linkMapper = opts.linkMapper || standardLinkMapper; + this.subdir = opts.subdir || ''; + this.date = new Date().toISOString(); + this.skipEmpty = opts.skipEmpty; + } + + getBreadcrumbHtml(node) { + let parent = node.getParent(); + const nodePath = []; + + while (parent) { + nodePath.push(parent); + parent = parent.getParent(); + } + + const linkPath = nodePath.map(ancestor => { + const target = this.linkMapper.relativePath(node, ancestor); + const name = ancestor.getRelativeName() || 'All files'; + return '' + name + ''; + }); + + linkPath.reverse(); + return linkPath.length > 0 + ? linkPath.join(' / ') + ' ' + node.getRelativeName() + : 'All files'; + } + + fillTemplate(node, templateData, context) { + const linkMapper = this.linkMapper; + const summary = node.getCoverageSummary(); + templateData.entity = node.getQualifiedName() || 'All files'; + templateData.metrics = summary; + templateData.reportClass = context.classForPercent( + 'statements', + summary.statements.pct + ); + templateData.pathHtml = this.getBreadcrumbHtml(node); + templateData.base = { + css: linkMapper.assetPath(node, 'base.css') + }; + templateData.sorter = { + js: linkMapper.assetPath(node, 'sorter.js'), + image: linkMapper.assetPath(node, 'sort-arrow-sprite.png') + }; + templateData.blockNavigation = { + js: linkMapper.assetPath(node, 'block-navigation.js') + }; + templateData.prettify = { + js: linkMapper.assetPath(node, 'prettify.js'), + css: linkMapper.assetPath(node, 'prettify.css') + }; + templateData.favicon = linkMapper.assetPath(node, 'favicon.png'); + } + + getTemplateData() { + return { datetime: this.date }; + } + + getWriter(context) { + if (!this.subdir) { + return context.writer; + } + return context.writer.writerForDir(this.subdir); + } + + onStart(root, context) { + const assetHeaders = { + '.js': '/* eslint-disable */\n' + }; + + ['.', 'vendor'].forEach(subdir => { + const writer = this.getWriter(context); + const srcDir = path.resolve(__dirname, 'assets', subdir); + fs.readdirSync(srcDir).forEach(f => { + const resolvedSource = path.resolve(srcDir, f); + const resolvedDestination = '.'; + const stat = fs.statSync(resolvedSource); + let dest; + + if (stat.isFile()) { + dest = resolvedDestination + '/' + f; + if (this.verbose) { + console.log('Write asset: ' + dest); + } + writer.copyFile( + resolvedSource, + dest, + assetHeaders[path.extname(f)] + ); + } + }); + }); + } + + onSummary(node, context) { + const linkMapper = this.linkMapper; + const templateData = this.getTemplateData(); + const children = node.getChildren(); + const skipEmpty = this.skipEmpty; + + this.fillTemplate(node, templateData, context); + const cw = this.getWriter(context).writeFile(linkMapper.getPath(node)); + cw.write(headerTemplate(templateData)); + cw.write(summaryTableHeader); + children.forEach(child => { + const metrics = child.getCoverageSummary(); + const isEmpty = metrics.isEmpty(); + if (skipEmpty && isEmpty) { + return; + } + const reportClasses = isEmpty + ? emptyClasses + : { + statements: context.classForPercent( + 'statements', + metrics.statements.pct + ), + lines: context.classForPercent( + 'lines', + metrics.lines.pct + ), + functions: context.classForPercent( + 'functions', + metrics.functions.pct + ), + branches: context.classForPercent( + 'branches', + metrics.branches.pct + ) + }; + const data = { + metrics: isEmpty ? fixPct(metrics) : metrics, + reportClasses, + file: child.getRelativeName(), + output: linkMapper.relativePath(node, child) + }; + cw.write(summaryLineTemplate(data) + '\n'); + }); + cw.write(summaryTableFooter); + cw.write(footerTemplate(templateData)); + cw.close(); + } + + onDetail(node, context) { + const linkMapper = this.linkMapper; + const templateData = this.getTemplateData(); + + this.fillTemplate(node, templateData, context); + const cw = this.getWriter(context).writeFile(linkMapper.getPath(node)); + cw.write(headerTemplate(templateData)); + cw.write('
\n');
+        cw.write(detailTemplate(annotator(node.getFileCoverage(), context)));
+        cw.write('
\n'); + cw.write(footerTemplate(templateData)); + cw.close(); + } +} + +module.exports = HtmlReport; diff --git a/node_modules/istanbul-reports/lib/html/insertion-text.js b/node_modules/istanbul-reports/lib/html/insertion-text.js new file mode 100644 index 0000000..6f80642 --- /dev/null +++ b/node_modules/istanbul-reports/lib/html/insertion-text.js @@ -0,0 +1,114 @@ +'use strict'; +/* + Copyright 2012-2015, Yahoo Inc. + Copyrights licensed under the New BSD License. See the accompanying LICENSE file for terms. + */ +function InsertionText(text, consumeBlanks) { + this.text = text; + this.origLength = text.length; + this.offsets = []; + this.consumeBlanks = consumeBlanks; + this.startPos = this.findFirstNonBlank(); + this.endPos = this.findLastNonBlank(); +} + +const WHITE_RE = /[ \f\n\r\t\v\u00A0\u2028\u2029]/; + +InsertionText.prototype = { + findFirstNonBlank() { + let pos = -1; + const text = this.text; + const len = text.length; + let i; + for (i = 0; i < len; i += 1) { + if (!text.charAt(i).match(WHITE_RE)) { + pos = i; + break; + } + } + return pos; + }, + findLastNonBlank() { + const text = this.text; + const len = text.length; + let pos = text.length + 1; + let i; + for (i = len - 1; i >= 0; i -= 1) { + if (!text.charAt(i).match(WHITE_RE)) { + pos = i; + break; + } + } + return pos; + }, + originalLength() { + return this.origLength; + }, + + insertAt(col, str, insertBefore, consumeBlanks) { + consumeBlanks = + typeof consumeBlanks === 'undefined' + ? this.consumeBlanks + : consumeBlanks; + col = col > this.originalLength() ? this.originalLength() : col; + col = col < 0 ? 0 : col; + + if (consumeBlanks) { + if (col <= this.startPos) { + col = 0; + } + if (col > this.endPos) { + col = this.origLength; + } + } + + const len = str.length; + const offset = this.findOffset(col, len, insertBefore); + const realPos = col + offset; + const text = this.text; + this.text = text.substring(0, realPos) + str + text.substring(realPos); + return this; + }, + + findOffset(pos, len, insertBefore) { + const offsets = this.offsets; + let offsetObj; + let cumulativeOffset = 0; + let i; + + for (i = 0; i < offsets.length; i += 1) { + offsetObj = offsets[i]; + if ( + offsetObj.pos < pos || + (offsetObj.pos === pos && !insertBefore) + ) { + cumulativeOffset += offsetObj.len; + } + if (offsetObj.pos >= pos) { + break; + } + } + if (offsetObj && offsetObj.pos === pos) { + offsetObj.len += len; + } else { + offsets.splice(i, 0, { pos, len }); + } + return cumulativeOffset; + }, + + wrap(startPos, startText, endPos, endText, consumeBlanks) { + this.insertAt(startPos, startText, true, consumeBlanks); + this.insertAt(endPos, endText, false, consumeBlanks); + return this; + }, + + wrapLine(startText, endText) { + this.wrap(0, startText, this.originalLength(), endText); + }, + + toString() { + return this.text; + } +}; + +module.exports = InsertionText; diff --git a/node_modules/istanbul-reports/lib/json-summary/index.js b/node_modules/istanbul-reports/lib/json-summary/index.js new file mode 100644 index 0000000..318a47f --- /dev/null +++ b/node_modules/istanbul-reports/lib/json-summary/index.js @@ -0,0 +1,56 @@ +/* + Copyright 2012-2015, Yahoo Inc. + Copyrights licensed under the New BSD License. See the accompanying LICENSE file for terms. + */ +'use strict'; +const { ReportBase } = require('istanbul-lib-report'); + +class JsonSummaryReport extends ReportBase { + constructor(opts) { + super(); + + this.file = opts.file || 'coverage-summary.json'; + this.contentWriter = null; + this.first = true; + } + + onStart(root, context) { + this.contentWriter = context.writer.writeFile(this.file); + this.contentWriter.write('{'); + } + + writeSummary(filePath, sc) { + const cw = this.contentWriter; + if (this.first) { + this.first = false; + } else { + cw.write(','); + } + cw.write(JSON.stringify(filePath)); + cw.write(': '); + cw.write(JSON.stringify(sc)); + cw.println(''); + } + + onSummary(node) { + if (!node.isRoot()) { + return; + } + this.writeSummary('total', node.getCoverageSummary()); + } + + onDetail(node) { + this.writeSummary( + node.getFileCoverage().path, + node.getCoverageSummary() + ); + } + + onEnd() { + const cw = this.contentWriter; + cw.println('}'); + cw.close(); + } +} + +module.exports = JsonSummaryReport; diff --git a/node_modules/istanbul-reports/lib/json/index.js b/node_modules/istanbul-reports/lib/json/index.js new file mode 100644 index 0000000..bcae6ae --- /dev/null +++ b/node_modules/istanbul-reports/lib/json/index.js @@ -0,0 +1,44 @@ +/* + Copyright 2012-2015, Yahoo Inc. + Copyrights licensed under the New BSD License. See the accompanying LICENSE file for terms. + */ +'use strict'; +const { ReportBase } = require('istanbul-lib-report'); + +class JsonReport extends ReportBase { + constructor(opts) { + super(); + + this.file = opts.file || 'coverage-final.json'; + this.first = true; + } + + onStart(root, context) { + this.contentWriter = context.writer.writeFile(this.file); + this.contentWriter.write('{'); + } + + onDetail(node) { + const fc = node.getFileCoverage(); + const key = fc.path; + const cw = this.contentWriter; + + if (this.first) { + this.first = false; + } else { + cw.write(','); + } + cw.write(JSON.stringify(key)); + cw.write(': '); + cw.write(JSON.stringify(fc)); + cw.println(''); + } + + onEnd() { + const cw = this.contentWriter; + cw.println('}'); + cw.close(); + } +} + +module.exports = JsonReport; diff --git a/node_modules/istanbul-reports/lib/lcov/index.js b/node_modules/istanbul-reports/lib/lcov/index.js new file mode 100644 index 0000000..383c202 --- /dev/null +++ b/node_modules/istanbul-reports/lib/lcov/index.js @@ -0,0 +1,33 @@ +'use strict'; +/* + Copyright 2012-2015, Yahoo Inc. + Copyrights licensed under the New BSD License. See the accompanying LICENSE file for terms. + */ +const { ReportBase } = require('istanbul-lib-report'); +const LcovOnlyReport = require('../lcovonly'); +const HtmlReport = require('../html'); + +class LcovReport extends ReportBase { + constructor(opts) { + super(); + this.lcov = new LcovOnlyReport({ file: 'lcov.info', ...opts }); + this.html = new HtmlReport({ subdir: 'lcov-report' }); + } +} + +['Start', 'End', 'Summary', 'SummaryEnd', 'Detail'].forEach(what => { + const meth = 'on' + what; + LcovReport.prototype[meth] = function(...args) { + const lcov = this.lcov; + const html = this.html; + + if (lcov[meth]) { + lcov[meth](...args); + } + if (html[meth]) { + html[meth](...args); + } + }; +}); + +module.exports = LcovReport; diff --git a/node_modules/istanbul-reports/lib/lcovonly/index.js b/node_modules/istanbul-reports/lib/lcovonly/index.js new file mode 100644 index 0000000..0720e46 --- /dev/null +++ b/node_modules/istanbul-reports/lib/lcovonly/index.js @@ -0,0 +1,77 @@ +/* + Copyright 2012-2015, Yahoo Inc. + Copyrights licensed under the New BSD License. See the accompanying LICENSE file for terms. + */ +'use strict'; +const { ReportBase } = require('istanbul-lib-report'); + +class LcovOnlyReport extends ReportBase { + constructor(opts) { + super(); + opts = opts || {}; + this.file = opts.file || 'lcov.info'; + this.projectRoot = opts.projectRoot || process.cwd(); + this.contentWriter = null; + } + + onStart(root, context) { + this.contentWriter = context.writer.writeFile(this.file); + } + + onDetail(node) { + const fc = node.getFileCoverage(); + const writer = this.contentWriter; + const functions = fc.f; + const functionMap = fc.fnMap; + const lines = fc.getLineCoverage(); + const branches = fc.b; + const branchMap = fc.branchMap; + const summary = node.getCoverageSummary(); + const path = require('path'); + + writer.println('TN:'); + const fileName = path.relative(this.projectRoot, fc.path); + writer.println('SF:' + fileName); + + Object.values(functionMap).forEach(meta => { + // Some versions of the instrumenter in the wild populate 'loc' + // but not 'decl': + const decl = meta.decl || meta.loc; + writer.println('FN:' + [decl.start.line, meta.name].join(',')); + }); + writer.println('FNF:' + summary.functions.total); + writer.println('FNH:' + summary.functions.covered); + + Object.entries(functionMap).forEach(([key, meta]) => { + const stats = functions[key]; + writer.println('FNDA:' + [stats, meta.name].join(',')); + }); + + Object.entries(lines).forEach(entry => { + writer.println('DA:' + entry.join(',')); + }); + writer.println('LF:' + summary.lines.total); + writer.println('LH:' + summary.lines.covered); + + Object.entries(branches).forEach(([key, branchArray]) => { + const meta = branchMap[key]; + if (meta) { + const { line } = meta.loc.start; + branchArray.forEach((b, i) => { + writer.println('BRDA:' + [line, key, i, b].join(',')); + }); + } else { + console.warn('Missing coverage entries in', fileName, key); + } + }); + writer.println('BRF:' + summary.branches.total); + writer.println('BRH:' + summary.branches.covered); + writer.println('end_of_record'); + } + + onEnd() { + this.contentWriter.close(); + } +} + +module.exports = LcovOnlyReport; diff --git a/node_modules/istanbul-reports/lib/none/index.js b/node_modules/istanbul-reports/lib/none/index.js new file mode 100644 index 0000000..81c1408 --- /dev/null +++ b/node_modules/istanbul-reports/lib/none/index.js @@ -0,0 +1,10 @@ +'use strict'; +/* + Copyright 2012-2015, Yahoo Inc. + Copyrights licensed under the New BSD License. See the accompanying LICENSE file for terms. + */ +const { ReportBase } = require('istanbul-lib-report'); + +class NoneReport extends ReportBase {} + +module.exports = NoneReport; diff --git a/node_modules/istanbul-reports/lib/teamcity/index.js b/node_modules/istanbul-reports/lib/teamcity/index.js new file mode 100644 index 0000000..2bca26a --- /dev/null +++ b/node_modules/istanbul-reports/lib/teamcity/index.js @@ -0,0 +1,67 @@ +/* + Copyright 2012-2015, Yahoo Inc. + Copyrights licensed under the New BSD License. See the accompanying LICENSE file for terms. + */ +'use strict'; +const { ReportBase } = require('istanbul-lib-report'); + +class TeamcityReport extends ReportBase { + constructor(opts) { + super(); + + opts = opts || {}; + this.file = opts.file || null; + this.blockName = opts.blockName || 'Code Coverage Summary'; + } + + onStart(node, context) { + const metrics = node.getCoverageSummary(); + const cw = context.writer.writeFile(this.file); + + cw.println(''); + cw.println("##teamcity[blockOpened name='" + this.blockName + "']"); + + //Statements Covered + cw.println( + lineForKey(metrics.statements.covered, 'CodeCoverageAbsBCovered') + ); + cw.println( + lineForKey(metrics.statements.total, 'CodeCoverageAbsBTotal') + ); + + //Branches Covered + cw.println( + lineForKey(metrics.branches.covered, 'CodeCoverageAbsRCovered') + ); + cw.println(lineForKey(metrics.branches.total, 'CodeCoverageAbsRTotal')); + + //Functions Covered + cw.println( + lineForKey(metrics.functions.covered, 'CodeCoverageAbsMCovered') + ); + cw.println( + lineForKey(metrics.functions.total, 'CodeCoverageAbsMTotal') + ); + + //Lines Covered + cw.println( + lineForKey(metrics.lines.covered, 'CodeCoverageAbsLCovered') + ); + cw.println(lineForKey(metrics.lines.total, 'CodeCoverageAbsLTotal')); + + cw.println("##teamcity[blockClosed name='" + this.blockName + "']"); + cw.close(); + } +} + +function lineForKey(value, teamcityVar) { + return ( + "##teamcity[buildStatisticValue key='" + + teamcityVar + + "' value='" + + value + + "']" + ); +} + +module.exports = TeamcityReport; diff --git a/node_modules/istanbul-reports/lib/text-lcov/index.js b/node_modules/istanbul-reports/lib/text-lcov/index.js new file mode 100644 index 0000000..847aedf --- /dev/null +++ b/node_modules/istanbul-reports/lib/text-lcov/index.js @@ -0,0 +1,17 @@ +'use strict'; +/* + Copyright 2012-2015, Yahoo Inc. + Copyrights licensed under the New BSD License. See the accompanying LICENSE file for terms. + */ +const LcovOnly = require('../lcovonly'); + +class TextLcov extends LcovOnly { + constructor(opts) { + super({ + ...opts, + file: '-' + }); + } +} + +module.exports = TextLcov; diff --git a/node_modules/istanbul-reports/lib/text-summary/index.js b/node_modules/istanbul-reports/lib/text-summary/index.js new file mode 100644 index 0000000..a9e6eab --- /dev/null +++ b/node_modules/istanbul-reports/lib/text-summary/index.js @@ -0,0 +1,62 @@ +/* + Copyright 2012-2015, Yahoo Inc. + Copyrights licensed under the New BSD License. See the accompanying LICENSE file for terms. + */ +'use strict'; +const { ReportBase } = require('istanbul-lib-report'); + +class TextSummaryReport extends ReportBase { + constructor(opts) { + super(); + + opts = opts || {}; + this.file = opts.file || null; + } + + onStart(node, context) { + const summary = node.getCoverageSummary(); + const cw = context.writer.writeFile(this.file); + const printLine = function(key) { + const str = lineForKey(summary, key); + const clazz = context.classForPercent(key, summary[key].pct); + cw.println(cw.colorize(str, clazz)); + }; + + cw.println(''); + cw.println( + '=============================== Coverage summary ===============================' + ); + printLine('statements'); + printLine('branches'); + printLine('functions'); + printLine('lines'); + cw.println( + '================================================================================' + ); + cw.close(); + } +} + +function lineForKey(summary, key) { + const metrics = summary[key]; + + key = key.substring(0, 1).toUpperCase() + key.substring(1); + if (key.length < 12) { + key += ' '.substring(0, 12 - key.length); + } + const result = [ + key, + ':', + metrics.pct + '%', + '(', + metrics.covered + '/' + metrics.total, + ')' + ].join(' '); + const skipped = metrics.skipped; + if (skipped > 0) { + return result + ', ' + skipped + ' ignored'; + } + return result; +} + +module.exports = TextSummaryReport; diff --git a/node_modules/istanbul-reports/lib/text/index.js b/node_modules/istanbul-reports/lib/text/index.js new file mode 100644 index 0000000..c28cedb --- /dev/null +++ b/node_modules/istanbul-reports/lib/text/index.js @@ -0,0 +1,298 @@ +/* + Copyright 2012-2015, Yahoo Inc. + Copyrights licensed under the New BSD License. See the accompanying LICENSE + file for terms. + */ +'use strict'; +const { ReportBase } = require('istanbul-lib-report'); + +const NAME_COL = 4; +const PCT_COLS = 7; +const MISSING_COL = 17; +const TAB_SIZE = 1; +const DELIM = ' | '; + +function padding(num, ch) { + let str = ''; + let i; + ch = ch || ' '; + for (i = 0; i < num; i += 1) { + str += ch; + } + return str; +} + +function fill(str, width, right, tabs) { + tabs = tabs || 0; + str = String(str); + + const leadingSpaces = tabs * TAB_SIZE; + const remaining = width - leadingSpaces; + const leader = padding(leadingSpaces); + let fmtStr = ''; + + if (remaining > 0) { + const strlen = str.length; + let fillStr; + + if (remaining >= strlen) { + fillStr = padding(remaining - strlen); + } else { + fillStr = '...'; + const length = remaining - fillStr.length; + + str = str.substring(strlen - length); + right = true; + } + fmtStr = right ? fillStr + str : str + fillStr; + } + + return leader + fmtStr; +} + +function formatName(name, maxCols, level) { + return fill(name, maxCols, false, level); +} + +function formatPct(pct, width) { + return fill(pct, width || PCT_COLS, true, 0); +} + +function nodeMissing(node) { + if (node.isSummary()) { + return ''; + } + + const metrics = node.getCoverageSummary(); + const isEmpty = metrics.isEmpty(); + const lines = isEmpty ? 0 : metrics.lines.pct; + + let coveredLines; + + const fileCoverage = node.getFileCoverage(); + if (lines === 100) { + const branches = fileCoverage.getBranchCoverageByLine(); + coveredLines = Object.entries(branches).map(([key, { coverage }]) => [ + key, + coverage === 100 + ]); + } else { + coveredLines = Object.entries(fileCoverage.getLineCoverage()); + } + + let newRange = true; + const ranges = coveredLines + .reduce((acum, [line, hit]) => { + if (hit) newRange = true; + else { + line = parseInt(line); + if (newRange) { + acum.push([line]); + newRange = false; + } else acum[acum.length - 1][1] = line; + } + + return acum; + }, []) + .map(range => { + const { length } = range; + + if (length === 1) return range[0]; + + return `${range[0]}-${range[1]}`; + }); + + return [].concat(...ranges).join(','); +} + +function nodeName(node) { + return node.getRelativeName() || 'All files'; +} + +function depthFor(node) { + let ret = 0; + node = node.getParent(); + while (node) { + ret += 1; + node = node.getParent(); + } + return ret; +} + +function nullDepthFor() { + return 0; +} + +function findWidth(node, context, nodeExtractor, depthFor = nullDepthFor) { + let last = 0; + function compareWidth(node) { + last = Math.max( + last, + TAB_SIZE * depthFor(node) + nodeExtractor(node).length + ); + } + const visitor = { + onSummary: compareWidth, + onDetail: compareWidth + }; + node.visit(context.getVisitor(visitor)); + return last; +} + +function makeLine(nameWidth, missingWidth) { + const name = padding(nameWidth, '-'); + const pct = padding(PCT_COLS, '-'); + const elements = []; + + elements.push(name); + elements.push(pct); + elements.push(padding(PCT_COLS + 1, '-')); + elements.push(pct); + elements.push(pct); + elements.push(padding(missingWidth, '-')); + return elements.join(DELIM.replace(/ /g, '-')) + '-'; +} + +function tableHeader(maxNameCols, missingWidth) { + const elements = []; + elements.push(formatName('File', maxNameCols, 0)); + elements.push(formatPct('% Stmts')); + elements.push(formatPct('% Branch', PCT_COLS + 1)); + elements.push(formatPct('% Funcs')); + elements.push(formatPct('% Lines')); + elements.push(formatName('Uncovered Line #s', missingWidth)); + return elements.join(DELIM) + ' '; +} + +function isFull(metrics) { + return ( + metrics.statements.pct === 100 && + metrics.branches.pct === 100 && + metrics.functions.pct === 100 && + metrics.lines.pct === 100 + ); +} + +function tableRow( + node, + context, + colorizer, + maxNameCols, + level, + skipEmpty, + skipFull, + missingWidth +) { + const name = nodeName(node); + const metrics = node.getCoverageSummary(); + const isEmpty = metrics.isEmpty(); + if (skipEmpty && isEmpty) { + return ''; + } + if (skipFull && isFull(metrics)) { + return ''; + } + + const mm = { + statements: isEmpty ? 0 : metrics.statements.pct, + branches: isEmpty ? 0 : metrics.branches.pct, + functions: isEmpty ? 0 : metrics.functions.pct, + lines: isEmpty ? 0 : metrics.lines.pct + }; + const colorize = isEmpty + ? function(str) { + return str; + } + : function(str, key) { + return colorizer(str, context.classForPercent(key, mm[key])); + }; + const elements = []; + + elements.push(colorize(formatName(name, maxNameCols, level), 'statements')); + elements.push(colorize(formatPct(mm.statements), 'statements')); + elements.push(colorize(formatPct(mm.branches, PCT_COLS + 1), 'branches')); + elements.push(colorize(formatPct(mm.functions), 'functions')); + elements.push(colorize(formatPct(mm.lines), 'lines')); + elements.push( + colorizer( + formatName(nodeMissing(node), missingWidth), + mm.lines === 100 ? 'medium' : 'low' + ) + ); + + return elements.join(DELIM) + ' '; +} + +class TextReport extends ReportBase { + constructor(opts) { + super(opts); + + opts = opts || {}; + const { maxCols } = opts; + + this.file = opts.file || null; + this.maxCols = maxCols != null ? maxCols : process.stdout.columns || 80; + this.cw = null; + this.skipEmpty = opts.skipEmpty; + this.skipFull = opts.skipFull; + } + + onStart(root, context) { + this.cw = context.writer.writeFile(this.file); + this.nameWidth = Math.max( + NAME_COL, + findWidth(root, context, nodeName, depthFor) + ); + this.missingWidth = Math.max( + MISSING_COL, + findWidth(root, context, nodeMissing) + ); + + if (this.maxCols > 0) { + const pct_cols = DELIM.length + 4 * (PCT_COLS + DELIM.length) + 2; + + const maxRemaining = this.maxCols - (pct_cols + MISSING_COL); + if (this.nameWidth > maxRemaining) { + this.nameWidth = maxRemaining; + this.missingWidth = MISSING_COL; + } else if (this.nameWidth < maxRemaining) { + const maxRemaining = this.maxCols - (this.nameWidth + pct_cols); + if (this.missingWidth > maxRemaining) { + this.missingWidth = maxRemaining; + } + } + } + const line = makeLine(this.nameWidth, this.missingWidth); + this.cw.println(line); + this.cw.println(tableHeader(this.nameWidth, this.missingWidth)); + this.cw.println(line); + } + + onSummary(node, context) { + const nodeDepth = depthFor(node); + const row = tableRow( + node, + context, + this.cw.colorize.bind(this.cw), + this.nameWidth, + nodeDepth, + this.skipEmpty, + this.skipFull, + this.missingWidth + ); + if (row) { + this.cw.println(row); + } + } + + onDetail(node, context) { + return this.onSummary(node, context); + } + + onEnd() { + this.cw.println(makeLine(this.nameWidth, this.missingWidth)); + this.cw.close(); + } +} + +module.exports = TextReport; diff --git a/node_modules/istanbul-reports/package.json b/node_modules/istanbul-reports/package.json new file mode 100644 index 0000000..cc668dd --- /dev/null +++ b/node_modules/istanbul-reports/package.json @@ -0,0 +1,60 @@ +{ + "name": "istanbul-reports", + "version": "3.2.0", + "description": "istanbul reports", + "author": "Krishnan Anantheswaran ", + "main": "index.js", + "files": [ + "index.js", + "lib" + ], + "scripts": { + "test": "nyc mocha --recursive", + "prepare": "webpack --config lib/html-spa/webpack.config.js --mode production", + "prepare:watch": "webpack --config lib/html-spa/webpack.config.js --watch --mode development" + }, + "dependencies": { + "html-escaper": "^2.0.0", + "istanbul-lib-report": "^3.0.0" + }, + "devDependencies": { + "@babel/core": "^7.7.5", + "@babel/preset-env": "^7.7.5", + "@babel/preset-react": "^7.7.4", + "babel-loader": "^8.0.6", + "chai": "^4.2.0", + "is-windows": "^1.0.2", + "istanbul-lib-coverage": "^3.0.0", + "mocha": "^6.2.2", + "nyc": "^15.0.0-beta.2", + "react": "^16.12.0", + "react-dom": "^16.12.0", + "webpack": "^4.41.2", + "webpack-cli": "^3.3.10" + }, + "license": "BSD-3-Clause", + "repository": { + "type": "git", + "url": "git+ssh://git@github.com/istanbuljs/istanbuljs.git", + "directory": "packages/istanbul-reports" + }, + "keywords": [ + "istanbul", + "reports" + ], + "bugs": { + "url": "https://github.com/istanbuljs/istanbuljs/issues" + }, + "homepage": "https://istanbul.js.org/", + "nyc": { + "exclude": [ + "lib/html/assets/**", + "lib/html-spa/assets/**", + "lib/html-spa/rollup.config.js", + "test/**" + ] + }, + "engines": { + "node": ">=8" + } +} diff --git a/node_modules/lz-utils/LICENSE b/node_modules/lz-utils/LICENSE new file mode 100644 index 0000000..9139430 --- /dev/null +++ b/node_modules/lz-utils/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2022 cenfun + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/node_modules/lz-utils/README.md b/node_modules/lz-utils/README.md new file mode 100644 index 0000000..c5c9c7e --- /dev/null +++ b/node_modules/lz-utils/README.md @@ -0,0 +1,82 @@ +# lz-utils - Utils for string compression + +[![](https://img.shields.io/npm/v/lz-utils)](https://www.npmjs.com/package/lz-utils) +![](https://img.shields.io/librariesio/github/cenfun/lz-utils) +![](https://img.shields.io/librariesio/dependents/npm/lz-utils) +[![](https://badgen.net/npm/dw/lz-utils)](https://www.npmjs.com/package/lz-utils) +![](https://img.shields.io/github/license/cenfun/lz-utils) + +* `deflateSync` and `deflate` + - Compress raw string and encode in base64 + - Node.js only + - The highest performance (Using native `zlib`) + - Synchronous and Asynchronous + - The smallest size (minified) `0.13KB` / `0.17KB` +* `inflateSync` and `inflate` + - Decompress base64 string to raw string + - Browser only (Using `Uint8Array` and `TextDecoder`) + - Higher performance (Using [tiny-inflate](https://github.com/foliojs/tiny-inflate)) + - Synchronous and Asynchronous/Multi-thread (Using Worker) + - Smaller size (minified) `3.16KB` / `3.62KB` +* `compress` / `decompress` + - Using [lz-string](https://github.com/pieroxy/lz-string) compress/decompress in base64 only + - Both browser and Node.js + - Normal performance + - Synchronous only + - The smallest size (minified) `1.75KB` / `1.67KB` +* `createScriptLoader` + - create script loader + + +## Install +```sh +npm install lz-utils +``` +## Usage +```js +import { + compress, decompress, + deflateSync, deflate, + inflateSync, inflate +} from 'lz-utils'; + +const raw = "this is string"; +const cs = compress(raw); +const ds = decompress(cs); + +``` + +## Examples +- [test.js](/scripts/test.js) +- [test.html](/test/test.html) + +## Business Requirements and Why lz-utils? +- The business here is to generate a lot of `html reports` to users or customers, so the report needs to be generated as `fast` as possible and the file size should be as `small` as possible. +- The possible process is to compress the report data and bundle it with the html file. When the user opens the html file in the browser, the report data will be `self-decompressed` and rendered in the browser. So that's why `inflate` browser only. +- Why `base64`? First of all, the data is stored in `JSON` format, which is easily serialized and compressed. At this time, we get `binary` data. Although its size is the smallest, it has many problems, such as `security issues` (CORS) because it is not JS type or object, so we need to convert binary data into JS string, and `base64` is a good choice. + + +## String Compression Benchmark +- [string-compression](https://github.com/cenfun/string-compression) lz-string, pako, uzip.js, fflate, tiny-inflate + + +## Link +* [https://github.com/pieroxy/lz-string](https://github.com/pieroxy/lz-string) +* [https://github.com/foliojs/tiny-inflate](https://github.com/foliojs/tiny-inflate) + +## Changelog + +* 2.1.0 + - added `createScriptLoader` + +* 2.0.2 + - added types + +* 2.0.0 + - added tiny-inflate + +* 1.0.7 + - added ESM supported + +* 1.0.5 + - added browser version \ No newline at end of file diff --git a/node_modules/lz-utils/dist/browser.js b/node_modules/lz-utils/dist/browser.js new file mode 100644 index 0000000..f477940 --- /dev/null +++ b/node_modules/lz-utils/dist/browser.js @@ -0,0 +1,2 @@ +(()=>{var _=(e,o)=>()=>(o||e((o={exports:{}}).exports,o),o.exports);var T=_((de,O)=>{var N=function(e,o,t){let n,r,c={},w={},l="",d="",b="",h=2,p=3,f=2,u=[],i=0,a=0,s;for(s=0;s>=1}else{for(r=1,n=0;n>=1}h--,h===0&&(h=Math.pow(2,f),f++),delete w[b]}else for(r=c[b],n=0;n>=1;h--,h===0&&(h=Math.pow(2,f),f++),c[d]=p++,b=String(l)}if(b!==""){if(Object.prototype.hasOwnProperty.call(w,b)){if(b.charCodeAt(0)<256){for(n=0;n>=1}else{for(r=1,n=0;n>=1}h--,h===0&&(h=Math.pow(2,f),f++),delete w[b]}else for(r=c[b],n=0;n>=1;h--,h===0&&(h=Math.pow(2,f),f++)}for(r=2,n=0;n>=1;for(;;)if(i<<=1,a===o-1){u.push(t(i));break}else a++;return u.join("")},P="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",F=function(e){let o=N(e,6,function(t){return P.charAt(t)});switch(o.length%4){case 0:return o;case 1:return`${o}===`;case 2:return`${o}==`;case 3:return`${o}=`;default:}};O.exports=function(e){return e===null||e===""||typeof e>"u"?"":F(e)}});var B=_((ve,S)=>{var A=String.fromCharCode,C="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",k={};function V(e,o){if(!k[e]){k[e]={};for(let t=0;t>=1,s.position===0&&(s.position=o,s.val=t(s.index++)),p|=(f>0?1:0)*i,i<<=1;switch(p){case 0:for(p=0,u=Math.pow(2,8),i=1;i!==u;)f=s.val&s.position,s.position>>=1,s.position===0&&(s.position=o,s.val=t(s.index++)),p|=(f>0?1:0)*i,i<<=1;a=A(p);break;case 1:for(p=0,u=Math.pow(2,16),i=1;i!==u;)f=s.val&s.position,s.position>>=1,s.position===0&&(s.position=o,s.val=t(s.index++)),p|=(f>0?1:0)*i,i<<=1;a=A(p);break;case 2:return"";default:}for(n[3]=a,h=a,d.push(a);;){if(s.index>e)return"";for(p=0,u=Math.pow(2,w),i=1;i!==u;)f=s.val&s.position,s.position>>=1,s.position===0&&(s.position=o,s.val=t(s.index++)),p|=(f>0?1:0)*i,i<<=1;switch(a=p){case 0:for(p=0,u=Math.pow(2,8),i=1;i!==u;)f=s.val&s.position,s.position>>=1,s.position===0&&(s.position=o,s.val=t(s.index++)),p|=(f>0?1:0)*i,i<<=1;n[c++]=A(p),a=c-1,r--;break;case 1:for(p=0,u=Math.pow(2,16),i=1;i!==u;)f=s.val&s.position,s.position>>=1,s.position===0&&(s.position=o,s.val=t(s.index++)),p|=(f>0?1:0)*i,i<<=1;n[c++]=A(p),a=c-1,r--;break;case 2:return d.join("");default:}if(r===0&&(r=Math.pow(2,w),w++),n[a])l=n[a];else if(a===c)l=h+h.charAt(0);else return null;d.push(l),n[c++]=h+l.charAt(0),r--,h=l,r===0&&(r=Math.pow(2,w),w++)}},te=function(e){return ee(e.length,32,function(o){return V(C,e.charAt(o))})};S.exports=function(e){return e===null||e===""||typeof e>"u"?"":te(e)}});var j=_((xe,D)=>{D.exports=`(()=>{var x=(e,n)=>()=>(n||e((n={exports:{}}).exports,n),n.exports);var S=x((V,R)=>{var _=0,p=-3;function b(){this.table=new Uint16Array(16),this.trans=new Uint16Array(288)}function N(e,n){this.source=e,this.sourceIndex=0,this.tag=0,this.bitcount=0,this.dest=n,this.destLen=0,this.ltree=new b,this.dtree=new b}var y=new b,k=new b,w=new Uint8Array(30),h=new Uint16Array(30),L=new Uint8Array(30),T=new Uint16Array(30),O=new Uint8Array([16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15]),A=new b,c=new Uint8Array(320);function D(e,n,r,a){var t,i;for(t=0;t>>=1,n}function u(e,n,r){if(!n)return r;for(;e.bitcount<24;)e.tag|=e.source[e.sourceIndex++]<>>16-n;return e.tag>>>=n,e.bitcount-=n,a+r}function v(e,n){for(;e.bitcount<24;)e.tag|=e.source[e.sourceIndex++]<>>=1,++t,r+=n.table[t],a-=n.table[t];while(a>=0);return e.tag=i,e.bitcount-=t,n.trans[r+a]}function C(e,n,r){var a,t,i,o,s,f;for(a=u(e,5,257),t=u(e,5,1),i=u(e,4,4),o=0;o<19;++o)c[o]=0;for(o=0;o8;)e.sourceIndex--,e.bitcount-=8;if(n=e.source[e.sourceIndex+1],n=256*n+e.source[e.sourceIndex],r=e.source[e.sourceIndex+3],r=256*r+e.source[e.sourceIndex+2],n!==(~r&65535))return p;for(e.sourceIndex+=4,a=n;a;--a)e.dest[e.destLen++]=e.source[e.sourceIndex++];return e.bitcount=0,_}function j(e,n){var r=new N(e,n),a,t,i;do{switch(a=B(r),t=u(r,2,0),t){case 0:i=K(r);break;case 1:i=U(r,y,k);break;case 2:C(r,r.ltree,r.dtree),i=U(r,r.ltree,r.dtree);break;default:i=p}if(i!==_)throw new Error("Data error")}while(!a);return r.destLen{var G=S(),H=e=>Uint8Array.from(atob(e),n=>n.charCodeAt(0)),J=e=>new TextDecoder().decode(e);q.exports=function(e){if(e){let[n,r]=e.split(".");if(n&&r){let a=H(n),t=new Uint8Array(parseInt(r));return G(a,t),J(t)}}}});var P=E();onmessage=function(e){postMessage(P(e.data))};postMessage("workerReady");})(); +`});var q=_((_e,R)=>{var re=j();R.exports=e=>new Promise(o=>{let t=new Worker(URL.createObjectURL(new Blob([re],{type:"application/javascript"})));t.onmessage=n=>{if(n.data==="workerReady"){t.postMessage(e);return}o(n.data),t.terminate()},t.onerror=n=>{o({error:n}),t.terminate()}})});var X=_((ye,Q)=>{var L=0,K=-3;function y(){this.table=new Uint16Array(16),this.trans=new Uint16Array(288)}function ne(e,o){this.source=e,this.sourceIndex=0,this.tag=0,this.bitcount=0,this.dest=o,this.destLen=0,this.ltree=new y,this.dtree=new y}var G=new y,H=new y,I=new Uint8Array(30),M=new Uint16Array(30),J=new Uint8Array(30),W=new Uint16Array(30),oe=new Uint8Array([16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15]),z=new y,v=new Uint8Array(320);function $(e,o,t,n){var r,c;for(r=0;r>>=1,o}function x(e,o,t){if(!o)return t;for(;e.bitcount<24;)e.tag|=e.source[e.sourceIndex++]<>>16-o;return e.tag>>>=o,e.bitcount-=o,n+t}function U(e,o){for(;e.bitcount<24;)e.tag|=e.source[e.sourceIndex++]<>>=1,++r,t+=o.table[r],n-=o.table[r];while(n>=0);return e.tag=c,e.bitcount-=r,o.trans[t+n]}function ae(e,o,t){var n,r,c,w,l,d;for(n=x(e,5,257),r=x(e,5,1),c=x(e,4,4),w=0;w<19;++w)v[w]=0;for(w=0;w8;)e.sourceIndex--,e.bitcount-=8;if(o=e.source[e.sourceIndex+1],o=256*o+e.source[e.sourceIndex],t=e.source[e.sourceIndex+3],t=256*t+e.source[e.sourceIndex+2],o!==(~t&65535))return K;for(e.sourceIndex+=4,n=o;n;--n)e.dest[e.destLen++]=e.source[e.sourceIndex++];return e.bitcount=0,L}function fe(e,o){var t=new ne(e,o),n,r,c;do{switch(n=se(t),r=x(t,2,0),r){case 0:c=ce(t);break;case 1:c=m(t,G,H);break;case 2:ae(t,t.ltree,t.dtree),c=m(t,t.ltree,t.dtree);break;default:c=K}if(c!==L)throw new Error("Data error")}while(!n);return t.destLen{var ue=X(),le=e=>Uint8Array.from(atob(e),o=>o.charCodeAt(0)),we=e=>new TextDecoder().decode(e);Y.exports=function(e){if(e){let[o,t]=e.split(".");if(o&&t){let n=le(o),r=new Uint8Array(parseInt(t));return ue(n,r),we(r)}}}});var be=self||window;be["lz-utils"]={compress:T(),decompress:B(),inflate:q(),inflateSync:Z()};})(); diff --git a/node_modules/lz-utils/dist/compress.js b/node_modules/lz-utils/dist/compress.js new file mode 100644 index 0000000..dad219e --- /dev/null +++ b/node_modules/lz-utils/dist/compress.js @@ -0,0 +1 @@ +var y=function(u,l,n){let o,c,a={},r={},d="",_="",f="",p=2,x=3,s=2,i=[],e=0,t=0,w;for(w=0;w>=1}else{for(c=1,o=0;o>=1}p--,p===0&&(p=Math.pow(2,s),s++),delete r[f]}else for(c=a[f],o=0;o>=1;p--,p===0&&(p=Math.pow(2,s),s++),a[_]=x++,f=String(d)}if(f!==""){if(Object.prototype.hasOwnProperty.call(r,f)){if(f.charCodeAt(0)<256){for(o=0;o>=1}else{for(c=1,o=0;o>=1}p--,p===0&&(p=Math.pow(2,s),s++),delete r[f]}else for(c=a[f],o=0;o>=1;p--,p===0&&(p=Math.pow(2,s),s++)}for(c=2,o=0;o>=1;for(;;)if(e<<=1,t===l-1){i.push(n(e));break}else t++;return i.join("")},h="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",A=function(u){let l=y(u,6,function(n){return h.charAt(n)});switch(l.length%4){case 0:return l;case 1:return`${l}===`;case 2:return`${l}==`;case 3:return`${l}=`;default:}};module.exports=function(u){return u===null||u===""||typeof u>"u"?"":A(u)}; diff --git a/node_modules/lz-utils/dist/create-script-loader.js b/node_modules/lz-utils/dist/create-script-loader.js new file mode 100644 index 0000000..56ff7aa --- /dev/null +++ b/node_modules/lz-utils/dist/create-script-loader.js @@ -0,0 +1 @@ +var t=(r,e)=>()=>(e||r((e={exports:{}}).exports,e),e.exports);var a=t((p,n)=>{n.exports='var a=(r,e)=>()=>(e||r((e={exports:{}}).exports,e),e.exports);var s=a((b,o)=>{o.exports=`(()=>{var x=(e,n)=>()=>(n||e((n={exports:{}}).exports,n),n.exports);var S=x((V,R)=>{var _=0,p=-3;function b(){this.table=new Uint16Array(16),this.trans=new Uint16Array(288)}function N(e,n){this.source=e,this.sourceIndex=0,this.tag=0,this.bitcount=0,this.dest=n,this.destLen=0,this.ltree=new b,this.dtree=new b}var y=new b,k=new b,w=new Uint8Array(30),h=new Uint16Array(30),L=new Uint8Array(30),T=new Uint16Array(30),O=new Uint8Array([16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15]),A=new b,c=new Uint8Array(320);function D(e,n,r,a){var t,i;for(t=0;t>>=1,n}function u(e,n,r){if(!n)return r;for(;e.bitcount<24;)e.tag|=e.source[e.sourceIndex++]<>>16-n;return e.tag>>>=n,e.bitcount-=n,a+r}function v(e,n){for(;e.bitcount<24;)e.tag|=e.source[e.sourceIndex++]<>>=1,++t,r+=n.table[t],a-=n.table[t];while(a>=0);return e.tag=i,e.bitcount-=t,n.trans[r+a]}function C(e,n,r){var a,t,i,o,s,f;for(a=u(e,5,257),t=u(e,5,1),i=u(e,4,4),o=0;o<19;++o)c[o]=0;for(o=0;o8;)e.sourceIndex--,e.bitcount-=8;if(n=e.source[e.sourceIndex+1],n=256*n+e.source[e.sourceIndex],r=e.source[e.sourceIndex+3],r=256*r+e.source[e.sourceIndex+2],n!==(~r&65535))return p;for(e.sourceIndex+=4,a=n;a;--a)e.dest[e.destLen++]=e.source[e.sourceIndex++];return e.bitcount=0,_}function j(e,n){var r=new N(e,n),a,t,i;do{switch(a=B(r),t=u(r,2,0),t){case 0:i=K(r);break;case 1:i=U(r,y,k);break;case 2:C(r,r.ltree,r.dtree),i=U(r,r.ltree,r.dtree);break;default:i=p}if(i!==_)throw new Error("Data error")}while(!a);return r.destLen{var G=S(),H=e=>Uint8Array.from(atob(e),n=>n.charCodeAt(0)),J=e=>new TextDecoder().decode(e);q.exports=function(e){if(e){let[n,r]=e.split(".");if(n&&r){let a=H(n),t=new Uint8Array(parseInt(r));return G(a,t),J(t)}}}});var P=E();onmessage=function(e){postMessage(P(e.data))};postMessage("workerReady");})();\n`});var c=a((l,i)=>{var u=s();i.exports=r=>new Promise(e=>{let t=new Worker(URL.createObjectURL(new Blob([u],{type:"application/javascript"})));t.onmessage=n=>{if(n.data==="workerReady"){t.postMessage(r);return}e(n.data),t.terminate()},t.onerror=n=>{e({error:n}),t.terminate()}})});var f=c();f("{placeholder}").then(r=>{let e=document.createElement("script");e.innerHTML=r,document.body.appendChild(e)});\n'});var s=t((v,o)=>{var c=require("zlib");o.exports=r=>{let e=Buffer.from(r),i=e.length;return`${c.deflateRawSync(e).toString("base64")}.${i}`}});var u=a(),f=s();module.exports=r=>u.replace("{placeholder}",f(r)); diff --git a/node_modules/lz-utils/dist/decompress.js b/node_modules/lz-utils/dist/decompress.js new file mode 100644 index 0000000..fbf647a --- /dev/null +++ b/node_modules/lz-utils/dist/decompress.js @@ -0,0 +1 @@ +var u=String.fromCharCode,x="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",M={};function k(t,c){if(!M[t]){M[t]={};for(let s=0;s>=1,i.position===0&&(i.position=c,i.val=s(i.index++)),n|=(e>0?1:0)*o,o<<=1;switch(n){case 0:for(n=0,r=Math.pow(2,8),o=1;o!==r;)e=i.val&i.position,i.position>>=1,i.position===0&&(i.position=c,i.val=s(i.index++)),n|=(e>0?1:0)*o,o<<=1;p=u(n);break;case 1:for(n=0,r=Math.pow(2,16),o=1;o!==r;)e=i.val&i.position,i.position>>=1,i.position===0&&(i.position=c,i.val=s(i.index++)),n|=(e>0?1:0)*o,o<<=1;p=u(n);break;case 2:return"";default:}for(l[3]=p,v=p,m.push(p);;){if(i.index>t)return"";for(n=0,r=Math.pow(2,h),o=1;o!==r;)e=i.val&i.position,i.position>>=1,i.position===0&&(i.position=c,i.val=s(i.index++)),n|=(e>0?1:0)*o,o<<=1;switch(p=n){case 0:for(n=0,r=Math.pow(2,8),o=1;o!==r;)e=i.val&i.position,i.position>>=1,i.position===0&&(i.position=c,i.val=s(i.index++)),n|=(e>0?1:0)*o,o<<=1;l[f++]=u(n),p=f-1,a--;break;case 1:for(n=0,r=Math.pow(2,16),o=1;o!==r;)e=i.val&i.position,i.position>>=1,i.position===0&&(i.position=c,i.val=s(i.index++)),n|=(e>0?1:0)*o,o<<=1;l[f++]=u(n),p=f-1,a--;break;case 2:return m.join("");default:}if(a===0&&(a=Math.pow(2,h),h++),l[p])w=l[p];else if(p===f)w=v+v.charAt(0);else return null;m.push(w),l[f++]=v+w.charAt(0),a--,v=w,a===0&&(a=Math.pow(2,h),h++)}},A=function(t){return y(t.length,32,function(c){return k(x,t.charAt(c))})};module.exports=function(t){return t===null||t===""||typeof t>"u"?"":A(t)}; diff --git a/node_modules/lz-utils/dist/deflate-sync.js b/node_modules/lz-utils/dist/deflate-sync.js new file mode 100644 index 0000000..6b9b095 --- /dev/null +++ b/node_modules/lz-utils/dist/deflate-sync.js @@ -0,0 +1 @@ +var n=require("zlib");module.exports=e=>{let t=Buffer.from(e),r=t.length;return`${n.deflateRawSync(t).toString("base64")}.${r}`}; diff --git a/node_modules/lz-utils/dist/deflate.js b/node_modules/lz-utils/dist/deflate.js new file mode 100644 index 0000000..0f98258 --- /dev/null +++ b/node_modules/lz-utils/dist/deflate.js @@ -0,0 +1 @@ +var u=require("zlib");module.exports=n=>new Promise(t=>{let e=Buffer.from(n),r=e.length;u.deflateRaw(e,(o,s)=>{if(o){t();return}let f=`${s.toString("base64")}.${r}`;t(f)})}); diff --git a/node_modules/lz-utils/dist/index.js b/node_modules/lz-utils/dist/index.js new file mode 100644 index 0000000..c1eb63c --- /dev/null +++ b/node_modules/lz-utils/dist/index.js @@ -0,0 +1,9 @@ +module.exports = { + compress: require('./compress.js'), + decompress: require('./decompress.js'), + deflate: require('./deflate.js'), + inflate: require('./inflate.js'), + deflateSync: require('./deflate-sync.js'), + inflateSync: require('./inflate-sync.js'), + createScriptLoader: require('./create-script-loader.js') +}; diff --git a/node_modules/lz-utils/dist/index.mjs b/node_modules/lz-utils/dist/index.mjs new file mode 100644 index 0000000..eca2d8a --- /dev/null +++ b/node_modules/lz-utils/dist/index.mjs @@ -0,0 +1,19 @@ +import compress from './compress.js'; +import decompress from './decompress.js'; + +import deflate from './deflate.js'; +import inflate from './inflate.js'; + +import deflateSync from './deflate-sync.js'; +import inflateSync from './inflate-sync.js'; + +export { + compress, + decompress, + + deflate, + inflate, + + deflateSync, + inflateSync +}; diff --git a/node_modules/lz-utils/dist/inflate-sync.js b/node_modules/lz-utils/dist/inflate-sync.js new file mode 100644 index 0000000..64a0cad --- /dev/null +++ b/node_modules/lz-utils/dist/inflate-sync.js @@ -0,0 +1 @@ +var F=(e,n)=>()=>(n||e((n={exports:{}}).exports,n),n.exports);var R=F((M,D)=>{var _=0,U=-3;function b(){this.table=new Uint16Array(16),this.trans=new Uint16Array(288)}function N(e,n){this.source=e,this.sourceIndex=0,this.tag=0,this.bitcount=0,this.dest=n,this.destLen=0,this.ltree=new b,this.dtree=new b}var k=new b,p=new b,h=new Uint8Array(30),w=new Uint16Array(30),y=new Uint8Array(30),L=new Uint16Array(30),O=new Uint8Array([16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15]),g=new b,c=new Uint8Array(320);function T(e,n,r,a){var t,i;for(t=0;t>>=1,n}function u(e,n,r){if(!n)return r;for(;e.bitcount<24;)e.tag|=e.source[e.sourceIndex++]<>>16-n;return e.tag>>>=n,e.bitcount-=n,a+r}function v(e,n){for(;e.bitcount<24;)e.tag|=e.source[e.sourceIndex++]<>>=1,++t,r+=n.table[t],a-=n.table[t];while(a>=0);return e.tag=i,e.bitcount-=t,n.trans[r+a]}function B(e,n,r){var a,t,i,o,s,f;for(a=u(e,5,257),t=u(e,5,1),i=u(e,4,4),o=0;o<19;++o)c[o]=0;for(o=0;o8;)e.sourceIndex--,e.bitcount-=8;if(n=e.source[e.sourceIndex+1],n=256*n+e.source[e.sourceIndex],r=e.source[e.sourceIndex+3],r=256*r+e.source[e.sourceIndex+2],n!==(~r&65535))return U;for(e.sourceIndex+=4,a=n;a;--a)e.dest[e.destLen++]=e.source[e.sourceIndex++];return e.bitcount=0,_}function K(e,n){var r=new N(e,n),a,t,i;do{switch(a=z(r),t=u(r,2,0),t){case 0:i=C(r);break;case 1:i=I(r,k,p);break;case 2:B(r,r.ltree,r.dtree),i=I(r,r.ltree,r.dtree);break;default:i=U}if(i!==_)throw new Error("Data error")}while(!a);return r.destLenUint8Array.from(atob(e),n=>n.charCodeAt(0)),H=e=>new TextDecoder().decode(e);module.exports=function(e){if(e){let[n,r]=e.split(".");if(n&&r){let a=G(n),t=new Uint8Array(parseInt(r));return j(a,t),H(t)}}}; diff --git a/node_modules/lz-utils/dist/inflate-worker-data.js b/node_modules/lz-utils/dist/inflate-worker-data.js new file mode 100644 index 0000000..2370764 --- /dev/null +++ b/node_modules/lz-utils/dist/inflate-worker-data.js @@ -0,0 +1 @@ +module.exports = "(()=>{var x=(e,n)=>()=>(n||e((n={exports:{}}).exports,n),n.exports);var S=x((V,R)=>{var _=0,p=-3;function b(){this.table=new Uint16Array(16),this.trans=new Uint16Array(288)}function N(e,n){this.source=e,this.sourceIndex=0,this.tag=0,this.bitcount=0,this.dest=n,this.destLen=0,this.ltree=new b,this.dtree=new b}var y=new b,k=new b,w=new Uint8Array(30),h=new Uint16Array(30),L=new Uint8Array(30),T=new Uint16Array(30),O=new Uint8Array([16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15]),A=new b,c=new Uint8Array(320);function D(e,n,r,a){var t,i;for(t=0;t>>=1,n}function u(e,n,r){if(!n)return r;for(;e.bitcount<24;)e.tag|=e.source[e.sourceIndex++]<>>16-n;return e.tag>>>=n,e.bitcount-=n,a+r}function v(e,n){for(;e.bitcount<24;)e.tag|=e.source[e.sourceIndex++]<>>=1,++t,r+=n.table[t],a-=n.table[t];while(a>=0);return e.tag=i,e.bitcount-=t,n.trans[r+a]}function C(e,n,r){var a,t,i,o,s,f;for(a=u(e,5,257),t=u(e,5,1),i=u(e,4,4),o=0;o<19;++o)c[o]=0;for(o=0;o8;)e.sourceIndex--,e.bitcount-=8;if(n=e.source[e.sourceIndex+1],n=256*n+e.source[e.sourceIndex],r=e.source[e.sourceIndex+3],r=256*r+e.source[e.sourceIndex+2],n!==(~r&65535))return p;for(e.sourceIndex+=4,a=n;a;--a)e.dest[e.destLen++]=e.source[e.sourceIndex++];return e.bitcount=0,_}function j(e,n){var r=new N(e,n),a,t,i;do{switch(a=B(r),t=u(r,2,0),t){case 0:i=K(r);break;case 1:i=U(r,y,k);break;case 2:C(r,r.ltree,r.dtree),i=U(r,r.ltree,r.dtree);break;default:i=p}if(i!==_)throw new Error(\"Data error\")}while(!a);return r.destLen{var G=S(),H=e=>Uint8Array.from(atob(e),n=>n.charCodeAt(0)),J=e=>new TextDecoder().decode(e);q.exports=function(e){if(e){let[n,r]=e.split(\".\");if(n&&r){let a=H(n),t=new Uint8Array(parseInt(r));return G(a,t),J(t)}}}});var P=E();onmessage=function(e){postMessage(P(e.data))};postMessage(\"workerReady\");})();\n"; \ No newline at end of file diff --git a/node_modules/lz-utils/dist/inflate-worker.js b/node_modules/lz-utils/dist/inflate-worker.js new file mode 100644 index 0000000..ed7019e --- /dev/null +++ b/node_modules/lz-utils/dist/inflate-worker.js @@ -0,0 +1 @@ +(()=>{var x=(e,n)=>()=>(n||e((n={exports:{}}).exports,n),n.exports);var S=x((V,R)=>{var _=0,p=-3;function b(){this.table=new Uint16Array(16),this.trans=new Uint16Array(288)}function N(e,n){this.source=e,this.sourceIndex=0,this.tag=0,this.bitcount=0,this.dest=n,this.destLen=0,this.ltree=new b,this.dtree=new b}var y=new b,k=new b,w=new Uint8Array(30),h=new Uint16Array(30),L=new Uint8Array(30),T=new Uint16Array(30),O=new Uint8Array([16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15]),A=new b,c=new Uint8Array(320);function D(e,n,r,a){var t,i;for(t=0;t>>=1,n}function u(e,n,r){if(!n)return r;for(;e.bitcount<24;)e.tag|=e.source[e.sourceIndex++]<>>16-n;return e.tag>>>=n,e.bitcount-=n,a+r}function v(e,n){for(;e.bitcount<24;)e.tag|=e.source[e.sourceIndex++]<>>=1,++t,r+=n.table[t],a-=n.table[t];while(a>=0);return e.tag=i,e.bitcount-=t,n.trans[r+a]}function C(e,n,r){var a,t,i,o,s,f;for(a=u(e,5,257),t=u(e,5,1),i=u(e,4,4),o=0;o<19;++o)c[o]=0;for(o=0;o8;)e.sourceIndex--,e.bitcount-=8;if(n=e.source[e.sourceIndex+1],n=256*n+e.source[e.sourceIndex],r=e.source[e.sourceIndex+3],r=256*r+e.source[e.sourceIndex+2],n!==(~r&65535))return p;for(e.sourceIndex+=4,a=n;a;--a)e.dest[e.destLen++]=e.source[e.sourceIndex++];return e.bitcount=0,_}function j(e,n){var r=new N(e,n),a,t,i;do{switch(a=B(r),t=u(r,2,0),t){case 0:i=K(r);break;case 1:i=U(r,y,k);break;case 2:C(r,r.ltree,r.dtree),i=U(r,r.ltree,r.dtree);break;default:i=p}if(i!==_)throw new Error("Data error")}while(!a);return r.destLen{var G=S(),H=e=>Uint8Array.from(atob(e),n=>n.charCodeAt(0)),J=e=>new TextDecoder().decode(e);q.exports=function(e){if(e){let[n,r]=e.split(".");if(n&&r){let a=H(n),t=new Uint8Array(parseInt(r));return G(a,t),J(t)}}}});var P=E();onmessage=function(e){postMessage(P(e.data))};postMessage("workerReady");})(); diff --git a/node_modules/lz-utils/dist/inflate.js b/node_modules/lz-utils/dist/inflate.js new file mode 100644 index 0000000..8430083 --- /dev/null +++ b/node_modules/lz-utils/dist/inflate.js @@ -0,0 +1,2 @@ +var s=(n,e)=>()=>(e||n((e={exports:{}}).exports,e),e.exports);var o=s((u,a)=>{a.exports=`(()=>{var x=(e,n)=>()=>(n||e((n={exports:{}}).exports,n),n.exports);var S=x((V,R)=>{var _=0,p=-3;function b(){this.table=new Uint16Array(16),this.trans=new Uint16Array(288)}function N(e,n){this.source=e,this.sourceIndex=0,this.tag=0,this.bitcount=0,this.dest=n,this.destLen=0,this.ltree=new b,this.dtree=new b}var y=new b,k=new b,w=new Uint8Array(30),h=new Uint16Array(30),L=new Uint8Array(30),T=new Uint16Array(30),O=new Uint8Array([16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15]),A=new b,c=new Uint8Array(320);function D(e,n,r,a){var t,i;for(t=0;t>>=1,n}function u(e,n,r){if(!n)return r;for(;e.bitcount<24;)e.tag|=e.source[e.sourceIndex++]<>>16-n;return e.tag>>>=n,e.bitcount-=n,a+r}function v(e,n){for(;e.bitcount<24;)e.tag|=e.source[e.sourceIndex++]<>>=1,++t,r+=n.table[t],a-=n.table[t];while(a>=0);return e.tag=i,e.bitcount-=t,n.trans[r+a]}function C(e,n,r){var a,t,i,o,s,f;for(a=u(e,5,257),t=u(e,5,1),i=u(e,4,4),o=0;o<19;++o)c[o]=0;for(o=0;o8;)e.sourceIndex--,e.bitcount-=8;if(n=e.source[e.sourceIndex+1],n=256*n+e.source[e.sourceIndex],r=e.source[e.sourceIndex+3],r=256*r+e.source[e.sourceIndex+2],n!==(~r&65535))return p;for(e.sourceIndex+=4,a=n;a;--a)e.dest[e.destLen++]=e.source[e.sourceIndex++];return e.bitcount=0,_}function j(e,n){var r=new N(e,n),a,t,i;do{switch(a=B(r),t=u(r,2,0),t){case 0:i=K(r);break;case 1:i=U(r,y,k);break;case 2:C(r,r.ltree,r.dtree),i=U(r,r.ltree,r.dtree);break;default:i=p}if(i!==_)throw new Error("Data error")}while(!a);return r.destLen{var G=S(),H=e=>Uint8Array.from(atob(e),n=>n.charCodeAt(0)),J=e=>new TextDecoder().decode(e);q.exports=function(e){if(e){let[n,r]=e.split(".");if(n&&r){let a=H(n),t=new Uint8Array(parseInt(r));return G(a,t),J(t)}}}});var P=E();onmessage=function(e){postMessage(P(e.data))};postMessage("workerReady");})(); +`});var i=o();module.exports=n=>new Promise(e=>{let r=new Worker(URL.createObjectURL(new Blob([i],{type:"application/javascript"})));r.onmessage=t=>{if(t.data==="workerReady"){r.postMessage(n);return}e(t.data),r.terminate()},r.onerror=t=>{e({error:t}),r.terminate()}}); diff --git a/node_modules/lz-utils/dist/script-loader-data.js b/node_modules/lz-utils/dist/script-loader-data.js new file mode 100644 index 0000000..6fa54ad --- /dev/null +++ b/node_modules/lz-utils/dist/script-loader-data.js @@ -0,0 +1 @@ +module.exports = "var a=(r,e)=>()=>(e||r((e={exports:{}}).exports,e),e.exports);var s=a((b,o)=>{o.exports=`(()=>{var x=(e,n)=>()=>(n||e((n={exports:{}}).exports,n),n.exports);var S=x((V,R)=>{var _=0,p=-3;function b(){this.table=new Uint16Array(16),this.trans=new Uint16Array(288)}function N(e,n){this.source=e,this.sourceIndex=0,this.tag=0,this.bitcount=0,this.dest=n,this.destLen=0,this.ltree=new b,this.dtree=new b}var y=new b,k=new b,w=new Uint8Array(30),h=new Uint16Array(30),L=new Uint8Array(30),T=new Uint16Array(30),O=new Uint8Array([16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15]),A=new b,c=new Uint8Array(320);function D(e,n,r,a){var t,i;for(t=0;t>>=1,n}function u(e,n,r){if(!n)return r;for(;e.bitcount<24;)e.tag|=e.source[e.sourceIndex++]<>>16-n;return e.tag>>>=n,e.bitcount-=n,a+r}function v(e,n){for(;e.bitcount<24;)e.tag|=e.source[e.sourceIndex++]<>>=1,++t,r+=n.table[t],a-=n.table[t];while(a>=0);return e.tag=i,e.bitcount-=t,n.trans[r+a]}function C(e,n,r){var a,t,i,o,s,f;for(a=u(e,5,257),t=u(e,5,1),i=u(e,4,4),o=0;o<19;++o)c[o]=0;for(o=0;o8;)e.sourceIndex--,e.bitcount-=8;if(n=e.source[e.sourceIndex+1],n=256*n+e.source[e.sourceIndex],r=e.source[e.sourceIndex+3],r=256*r+e.source[e.sourceIndex+2],n!==(~r&65535))return p;for(e.sourceIndex+=4,a=n;a;--a)e.dest[e.destLen++]=e.source[e.sourceIndex++];return e.bitcount=0,_}function j(e,n){var r=new N(e,n),a,t,i;do{switch(a=B(r),t=u(r,2,0),t){case 0:i=K(r);break;case 1:i=U(r,y,k);break;case 2:C(r,r.ltree,r.dtree),i=U(r,r.ltree,r.dtree);break;default:i=p}if(i!==_)throw new Error(\"Data error\")}while(!a);return r.destLen{var G=S(),H=e=>Uint8Array.from(atob(e),n=>n.charCodeAt(0)),J=e=>new TextDecoder().decode(e);q.exports=function(e){if(e){let[n,r]=e.split(\".\");if(n&&r){let a=H(n),t=new Uint8Array(parseInt(r));return G(a,t),J(t)}}}});var P=E();onmessage=function(e){postMessage(P(e.data))};postMessage(\"workerReady\");})();\n`});var c=a((l,i)=>{var u=s();i.exports=r=>new Promise(e=>{let t=new Worker(URL.createObjectURL(new Blob([u],{type:\"application/javascript\"})));t.onmessage=n=>{if(n.data===\"workerReady\"){t.postMessage(r);return}e(n.data),t.terminate()},t.onerror=n=>{e({error:n}),t.terminate()}})});var f=c();f(\"{placeholder}\").then(r=>{let e=document.createElement(\"script\");e.innerHTML=r,document.body.appendChild(e)});\n"; \ No newline at end of file diff --git a/node_modules/lz-utils/dist/script-loader.js b/node_modules/lz-utils/dist/script-loader.js new file mode 100644 index 0000000..2e116ad --- /dev/null +++ b/node_modules/lz-utils/dist/script-loader.js @@ -0,0 +1,2 @@ +var a=(r,e)=>()=>(e||r((e={exports:{}}).exports,e),e.exports);var s=a((b,o)=>{o.exports=`(()=>{var x=(e,n)=>()=>(n||e((n={exports:{}}).exports,n),n.exports);var S=x((V,R)=>{var _=0,p=-3;function b(){this.table=new Uint16Array(16),this.trans=new Uint16Array(288)}function N(e,n){this.source=e,this.sourceIndex=0,this.tag=0,this.bitcount=0,this.dest=n,this.destLen=0,this.ltree=new b,this.dtree=new b}var y=new b,k=new b,w=new Uint8Array(30),h=new Uint16Array(30),L=new Uint8Array(30),T=new Uint16Array(30),O=new Uint8Array([16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15]),A=new b,c=new Uint8Array(320);function D(e,n,r,a){var t,i;for(t=0;t>>=1,n}function u(e,n,r){if(!n)return r;for(;e.bitcount<24;)e.tag|=e.source[e.sourceIndex++]<>>16-n;return e.tag>>>=n,e.bitcount-=n,a+r}function v(e,n){for(;e.bitcount<24;)e.tag|=e.source[e.sourceIndex++]<>>=1,++t,r+=n.table[t],a-=n.table[t];while(a>=0);return e.tag=i,e.bitcount-=t,n.trans[r+a]}function C(e,n,r){var a,t,i,o,s,f;for(a=u(e,5,257),t=u(e,5,1),i=u(e,4,4),o=0;o<19;++o)c[o]=0;for(o=0;o8;)e.sourceIndex--,e.bitcount-=8;if(n=e.source[e.sourceIndex+1],n=256*n+e.source[e.sourceIndex],r=e.source[e.sourceIndex+3],r=256*r+e.source[e.sourceIndex+2],n!==(~r&65535))return p;for(e.sourceIndex+=4,a=n;a;--a)e.dest[e.destLen++]=e.source[e.sourceIndex++];return e.bitcount=0,_}function j(e,n){var r=new N(e,n),a,t,i;do{switch(a=B(r),t=u(r,2,0),t){case 0:i=K(r);break;case 1:i=U(r,y,k);break;case 2:C(r,r.ltree,r.dtree),i=U(r,r.ltree,r.dtree);break;default:i=p}if(i!==_)throw new Error("Data error")}while(!a);return r.destLen{var G=S(),H=e=>Uint8Array.from(atob(e),n=>n.charCodeAt(0)),J=e=>new TextDecoder().decode(e);q.exports=function(e){if(e){let[n,r]=e.split(".");if(n&&r){let a=H(n),t=new Uint8Array(parseInt(r));return G(a,t),J(t)}}}});var P=E();onmessage=function(e){postMessage(P(e.data))};postMessage("workerReady");})(); +`});var c=a((l,i)=>{var u=s();i.exports=r=>new Promise(e=>{let t=new Worker(URL.createObjectURL(new Blob([u],{type:"application/javascript"})));t.onmessage=n=>{if(n.data==="workerReady"){t.postMessage(r);return}e(n.data),t.terminate()},t.onerror=n=>{e({error:n}),t.terminate()}})});var f=c();f("{placeholder}").then(r=>{let e=document.createElement("script");e.innerHTML=r,document.body.appendChild(e)}); diff --git a/node_modules/lz-utils/lib/browser.js b/node_modules/lz-utils/lib/browser.js new file mode 100644 index 0000000..fb0dded --- /dev/null +++ b/node_modules/lz-utils/lib/browser.js @@ -0,0 +1,7 @@ +const root = self || window; +root['lz-utils'] = { + compress: require('./compress.js'), + decompress: require('./decompress.js'), + inflate: require('./inflate.js'), + inflateSync: require('./inflate-sync.js') +}; diff --git a/node_modules/lz-utils/lib/compress.js b/node_modules/lz-utils/lib/compress.js new file mode 100644 index 0000000..8b341de --- /dev/null +++ b/node_modules/lz-utils/lib/compress.js @@ -0,0 +1,244 @@ + +// https://github.com/pieroxy/lz-string +// https://pieroxy.net/blog/pages/lz-string/index.html +/* eslint-disable max-statements,complexity,no-constant-condition,max-depth */ + +const _compress = function(uncompressed, bitsPerChar, getCharFromInt) { + let i; + let value; + const context_dictionary = {}; + const context_dictionaryToCreate = {}; + let context_c = ''; + let context_wc = ''; + let context_w = ''; + let context_enlargeIn = 2; + let context_dictSize = 3; + let context_numBits = 2; + const context_data = []; + let context_data_val = 0; + let context_data_position = 0; + let ii; + + for (ii = 0; ii < uncompressed.length; ii += 1) { + context_c = uncompressed.charAt(ii); + if (!Object.prototype.hasOwnProperty.call(context_dictionary, context_c)) { + context_dictionary[context_c] = context_dictSize++; + context_dictionaryToCreate[context_c] = true; + } + + context_wc = context_w + context_c; + if (Object.prototype.hasOwnProperty.call(context_dictionary, context_wc)) { + context_w = context_wc; + } else { + if (Object.prototype.hasOwnProperty.call(context_dictionaryToCreate, context_w)) { + if (context_w.charCodeAt(0) < 256) { + for (i = 0; i < context_numBits; i++) { + context_data_val <<= 1; + if (context_data_position === bitsPerChar - 1) { + context_data_position = 0; + context_data.push(getCharFromInt(context_data_val)); + context_data_val = 0; + } else { + context_data_position++; + } + } + value = context_w.charCodeAt(0); + for (i = 0; i < 8; i++) { + context_data_val = (context_data_val << 1) | (value & 1); + if (context_data_position === bitsPerChar - 1) { + context_data_position = 0; + context_data.push(getCharFromInt(context_data_val)); + context_data_val = 0; + } else { + context_data_position++; + } + value >>= 1; + } + } else { + value = 1; + for (i = 0; i < context_numBits; i++) { + context_data_val = (context_data_val << 1) | value; + if (context_data_position === bitsPerChar - 1) { + context_data_position = 0; + context_data.push(getCharFromInt(context_data_val)); + context_data_val = 0; + } else { + context_data_position++; + } + value = 0; + } + value = context_w.charCodeAt(0); + for (i = 0; i < 16; i++) { + context_data_val = (context_data_val << 1) | (value & 1); + if (context_data_position === bitsPerChar - 1) { + context_data_position = 0; + context_data.push(getCharFromInt(context_data_val)); + context_data_val = 0; + } else { + context_data_position++; + } + value >>= 1; + } + } + context_enlargeIn--; + if (context_enlargeIn === 0) { + context_enlargeIn = Math.pow(2, context_numBits); + context_numBits++; + } + delete context_dictionaryToCreate[context_w]; + } else { + value = context_dictionary[context_w]; + for (i = 0; i < context_numBits; i++) { + context_data_val = (context_data_val << 1) | (value & 1); + if (context_data_position === bitsPerChar - 1) { + context_data_position = 0; + context_data.push(getCharFromInt(context_data_val)); + context_data_val = 0; + } else { + context_data_position++; + } + value >>= 1; + } + + + } + context_enlargeIn--; + if (context_enlargeIn === 0) { + context_enlargeIn = Math.pow(2, context_numBits); + context_numBits++; + } + // Add wc to the dictionary. + context_dictionary[context_wc] = context_dictSize++; + context_w = String(context_c); + } + } + + // Output the code for w. + if (context_w !== '') { + if (Object.prototype.hasOwnProperty.call(context_dictionaryToCreate, context_w)) { + if (context_w.charCodeAt(0) < 256) { + for (i = 0; i < context_numBits; i++) { + context_data_val <<= 1; + if (context_data_position === bitsPerChar - 1) { + context_data_position = 0; + context_data.push(getCharFromInt(context_data_val)); + context_data_val = 0; + } else { + context_data_position++; + } + } + value = context_w.charCodeAt(0); + for (i = 0; i < 8; i++) { + context_data_val = (context_data_val << 1) | (value & 1); + if (context_data_position === bitsPerChar - 1) { + context_data_position = 0; + context_data.push(getCharFromInt(context_data_val)); + context_data_val = 0; + } else { + context_data_position++; + } + value >>= 1; + } + } else { + value = 1; + for (i = 0; i < context_numBits; i++) { + context_data_val = (context_data_val << 1) | value; + if (context_data_position === bitsPerChar - 1) { + context_data_position = 0; + context_data.push(getCharFromInt(context_data_val)); + context_data_val = 0; + } else { + context_data_position++; + } + value = 0; + } + value = context_w.charCodeAt(0); + for (i = 0; i < 16; i++) { + context_data_val = (context_data_val << 1) | (value & 1); + if (context_data_position === bitsPerChar - 1) { + context_data_position = 0; + context_data.push(getCharFromInt(context_data_val)); + context_data_val = 0; + } else { + context_data_position++; + } + value >>= 1; + } + } + context_enlargeIn--; + if (context_enlargeIn === 0) { + context_enlargeIn = Math.pow(2, context_numBits); + context_numBits++; + } + delete context_dictionaryToCreate[context_w]; + } else { + value = context_dictionary[context_w]; + for (i = 0; i < context_numBits; i++) { + context_data_val = (context_data_val << 1) | (value & 1); + if (context_data_position === bitsPerChar - 1) { + context_data_position = 0; + context_data.push(getCharFromInt(context_data_val)); + context_data_val = 0; + } else { + context_data_position++; + } + value >>= 1; + } + + + } + context_enlargeIn--; + if (context_enlargeIn === 0) { + context_enlargeIn = Math.pow(2, context_numBits); + context_numBits++; + } + } + + // Mark the end of the stream + value = 2; + for (i = 0; i < context_numBits; i++) { + context_data_val = (context_data_val << 1) | (value & 1); + if (context_data_position === bitsPerChar - 1) { + context_data_position = 0; + context_data.push(getCharFromInt(context_data_val)); + context_data_val = 0; + } else { + context_data_position++; + } + value >>= 1; + } + + // Flush the last char + while (true) { + context_data_val <<= 1; + if (context_data_position === bitsPerChar - 1) { + context_data.push(getCharFromInt(context_data_val)); + break; + } else { + context_data_position++; + } + } + return context_data.join(''); +}; + +const keyStrBase64 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/='; +const compressToBase64 = function(input) { + const res = _compress(input, 6, function(a) { + return keyStrBase64.charAt(a); + }); + switch (res.length % 4) { + case 0: return res; + case 1: return `${res}===`; + case 2: return `${res}==`; + case 3: return `${res}=`; + default: + } +}; + +module.exports = function(input) { + if (input === null || input === '' || typeof input === 'undefined') { + return ''; + } + // 166% bigger + return compressToBase64(input); +}; diff --git a/node_modules/lz-utils/lib/create-script-loader.js b/node_modules/lz-utils/lib/create-script-loader.js new file mode 100644 index 0000000..3311807 --- /dev/null +++ b/node_modules/lz-utils/lib/create-script-loader.js @@ -0,0 +1,5 @@ +const loader = require('../dist/script-loader-data.js'); +const deflateSync = require('./deflate-sync.js'); +module.exports = (str) => { + return loader.replace('{placeholder}', deflateSync(str)); +}; diff --git a/node_modules/lz-utils/lib/decompress.js b/node_modules/lz-utils/lib/decompress.js new file mode 100644 index 0000000..91cf34d --- /dev/null +++ b/node_modules/lz-utils/lib/decompress.js @@ -0,0 +1,201 @@ + +// https://github.com/pieroxy/lz-string +// https://pieroxy.net/blog/pages/lz-string/index.html +/* eslint-disable max-statements,complexity,no-constant-condition */ + +const fcc = String.fromCharCode; +const keyStrBase64 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/='; +const baseReverseDic = {}; + +function getBaseValue(alphabet, character) { + if (!baseReverseDic[alphabet]) { + baseReverseDic[alphabet] = {}; + for (let i = 0; i < alphabet.length; i++) { + baseReverseDic[alphabet][alphabet.charAt(i)] = i; + } + } + return baseReverseDic[alphabet][character]; +} + +const _decompress = function(length, resetValue, getNextValue) { + const dictionary = []; + + let enlargeIn = 4; + let dictSize = 4; + let numBits = 3; + let entry = ''; + const result = []; + let i; + let w; + let bits; + let resb; + let maxpower; + let power; + let c; + const data = { + val: getNextValue(0), position: resetValue, index: 1 + }; + + for (i = 0; i < 3; i += 1) { + dictionary[i] = i; + } + + bits = 0; + maxpower = Math.pow(2, 2); + power = 1; + while (power !== maxpower) { + resb = data.val & data.position; + data.position >>= 1; + if (data.position === 0) { + data.position = resetValue; + data.val = getNextValue(data.index++); + } + bits |= (resb > 0 ? 1 : 0) * power; + power <<= 1; + } + + const next = bits; + switch (next) { + case 0: + bits = 0; + maxpower = Math.pow(2, 8); + power = 1; + while (power !== maxpower) { + resb = data.val & data.position; + data.position >>= 1; + if (data.position === 0) { + data.position = resetValue; + data.val = getNextValue(data.index++); + } + bits |= (resb > 0 ? 1 : 0) * power; + power <<= 1; + } + c = fcc(bits); + break; + case 1: + bits = 0; + maxpower = Math.pow(2, 16); + power = 1; + while (power !== maxpower) { + resb = data.val & data.position; + data.position >>= 1; + if (data.position === 0) { + data.position = resetValue; + data.val = getNextValue(data.index++); + } + bits |= (resb > 0 ? 1 : 0) * power; + power <<= 1; + } + c = fcc(bits); + break; + case 2: + return ''; + default: + } + dictionary[3] = c; + w = c; + result.push(c); + while (true) { + if (data.index > length) { + return ''; + } + + bits = 0; + maxpower = Math.pow(2, numBits); + power = 1; + while (power !== maxpower) { + resb = data.val & data.position; + data.position >>= 1; + if (data.position === 0) { + data.position = resetValue; + data.val = getNextValue(data.index++); + } + bits |= (resb > 0 ? 1 : 0) * power; + power <<= 1; + } + + switch (c = bits) { + case 0: + bits = 0; + maxpower = Math.pow(2, 8); + power = 1; + while (power !== maxpower) { + resb = data.val & data.position; + data.position >>= 1; + if (data.position === 0) { + data.position = resetValue; + data.val = getNextValue(data.index++); + } + bits |= (resb > 0 ? 1 : 0) * power; + power <<= 1; + } + + dictionary[dictSize++] = fcc(bits); + c = dictSize - 1; + enlargeIn--; + break; + case 1: + bits = 0; + maxpower = Math.pow(2, 16); + power = 1; + while (power !== maxpower) { + resb = data.val & data.position; + data.position >>= 1; + if (data.position === 0) { + data.position = resetValue; + data.val = getNextValue(data.index++); + } + bits |= (resb > 0 ? 1 : 0) * power; + power <<= 1; + } + dictionary[dictSize++] = fcc(bits); + c = dictSize - 1; + enlargeIn--; + break; + case 2: + return result.join(''); + default: + } + + if (enlargeIn === 0) { + enlargeIn = Math.pow(2, numBits); + numBits++; + } + + if (dictionary[c]) { + entry = dictionary[c]; + } else { + if (c === dictSize) { + entry = w + w.charAt(0); + } else { + return null; + } + } + result.push(entry); + + // Add w+entry[0] to the dictionary. + dictionary[dictSize++] = w + entry.charAt(0); + enlargeIn--; + + w = entry; + + if (enlargeIn === 0) { + enlargeIn = Math.pow(2, numBits); + numBits++; + } + + } +}; + +const decompressFromBase64 = function(input) { + return _decompress(input.length, 32, function(index) { + return getBaseValue(keyStrBase64, input.charAt(index)); + }); +}; + +module.exports = function(input) { + if (input === null || input === '' || typeof input === 'undefined') { + return ''; + } + return decompressFromBase64(input); +}; diff --git a/node_modules/lz-utils/lib/deflate-sync.js b/node_modules/lz-utils/lib/deflate-sync.js new file mode 100644 index 0000000..d962e41 --- /dev/null +++ b/node_modules/lz-utils/lib/deflate-sync.js @@ -0,0 +1,9 @@ +const zlib = require('zlib'); +module.exports = (str) => { + const buf = Buffer.from(str); + const length = buf.length; + const buffer = zlib.deflateRawSync(buf); + const b64 = buffer.toString('base64'); + const result = `${b64}.${length}`; + return result; +}; diff --git a/node_modules/lz-utils/lib/deflate.js b/node_modules/lz-utils/lib/deflate.js new file mode 100644 index 0000000..1a0f32d --- /dev/null +++ b/node_modules/lz-utils/lib/deflate.js @@ -0,0 +1,16 @@ +const zlib = require('zlib'); +module.exports = (str) => { + return new Promise((resolve) => { + const buf = Buffer.from(str); + const length = buf.length; + zlib.deflateRaw(buf, (err, buffer) => { + if (err) { + resolve(); + return; + } + const b64 = buffer.toString('base64'); + const result = `${b64}.${length}`; + resolve(result); + }); + }); +}; diff --git a/node_modules/lz-utils/lib/index.d.ts b/node_modules/lz-utils/lib/index.d.ts new file mode 100644 index 0000000..c9f4f93 --- /dev/null +++ b/node_modules/lz-utils/lib/index.d.ts @@ -0,0 +1,14 @@ +declare namespace LZ { + function compress(input: string): string; + function decompress(input: string): string; + + function deflateSync(input: string): string; + function deflate(input: string): Promise; + + function inflateSync(input: string): string; + function inflate(input: string): Promise; + + function createScriptLoader(input: string): string; +} + +export = LZ \ No newline at end of file diff --git a/node_modules/lz-utils/lib/index.js b/node_modules/lz-utils/lib/index.js new file mode 100644 index 0000000..c1eb63c --- /dev/null +++ b/node_modules/lz-utils/lib/index.js @@ -0,0 +1,9 @@ +module.exports = { + compress: require('./compress.js'), + decompress: require('./decompress.js'), + deflate: require('./deflate.js'), + inflate: require('./inflate.js'), + deflateSync: require('./deflate-sync.js'), + inflateSync: require('./inflate-sync.js'), + createScriptLoader: require('./create-script-loader.js') +}; diff --git a/node_modules/lz-utils/lib/index.mjs b/node_modules/lz-utils/lib/index.mjs new file mode 100644 index 0000000..eca2d8a --- /dev/null +++ b/node_modules/lz-utils/lib/index.mjs @@ -0,0 +1,19 @@ +import compress from './compress.js'; +import decompress from './decompress.js'; + +import deflate from './deflate.js'; +import inflate from './inflate.js'; + +import deflateSync from './deflate-sync.js'; +import inflateSync from './inflate-sync.js'; + +export { + compress, + decompress, + + deflate, + inflate, + + deflateSync, + inflateSync +}; diff --git a/node_modules/lz-utils/lib/inflate-sync.js b/node_modules/lz-utils/lib/inflate-sync.js new file mode 100644 index 0000000..04b14ce --- /dev/null +++ b/node_modules/lz-utils/lib/inflate-sync.js @@ -0,0 +1,18 @@ +const inflate = require('tiny-inflate'); + +const base64ToUint8 = (str) => Uint8Array.from(atob(str), (c) => c.charCodeAt(0)); + +const uint8ArrToString = (uint8arr) => new TextDecoder().decode(uint8arr); + +module.exports = function(compressedB64) { + if (compressedB64) { + const [b64Str, sizeStr] = compressedB64.split('.'); + if (b64Str && sizeStr) { + const compressedBuffer = base64ToUint8(b64Str); + const outputBuffer = new Uint8Array(parseInt(sizeStr)); + inflate(compressedBuffer, outputBuffer); + return uint8ArrToString(outputBuffer); + } + } +}; + diff --git a/node_modules/lz-utils/lib/inflate-worker.js b/node_modules/lz-utils/lib/inflate-worker.js new file mode 100644 index 0000000..9d27bde --- /dev/null +++ b/node_modules/lz-utils/lib/inflate-worker.js @@ -0,0 +1,5 @@ +const inflateSync = require('./inflate-sync.js'); +onmessage = function(e) { + postMessage(inflateSync(e.data)); +}; +postMessage('workerReady'); diff --git a/node_modules/lz-utils/lib/inflate.js b/node_modules/lz-utils/lib/inflate.js new file mode 100644 index 0000000..9493797 --- /dev/null +++ b/node_modules/lz-utils/lib/inflate.js @@ -0,0 +1,22 @@ +const workerData = require('../dist/inflate-worker-data.js'); +module.exports = (compressedB64) => { + return new Promise((resolve) => { + const worker = new Worker(URL.createObjectURL(new Blob([workerData], { + type: 'application/javascript' + }))); + worker.onmessage = (e) => { + if (e.data === 'workerReady') { + worker.postMessage(compressedB64); + return; + } + resolve(e.data); + worker.terminate(); + }; + worker.onerror = (err) => { + resolve({ + error: err + }); + worker.terminate(); + }; + }); +}; diff --git a/node_modules/lz-utils/lib/script-loader.js b/node_modules/lz-utils/lib/script-loader.js new file mode 100644 index 0000000..6144283 --- /dev/null +++ b/node_modules/lz-utils/lib/script-loader.js @@ -0,0 +1,6 @@ +const inflate = require('./inflate.js'); +inflate('{placeholder}').then((res) => { + const script = document.createElement('script'); + script.innerHTML = res; + document.body.appendChild(script); +}); diff --git a/node_modules/lz-utils/package.json b/node_modules/lz-utils/package.json new file mode 100644 index 0000000..8ecfd62 --- /dev/null +++ b/node_modules/lz-utils/package.json @@ -0,0 +1,51 @@ +{ + "name": "lz-utils", + "version": "2.1.0", + "description": "lz-utils", + "main": "./dist/index.js", + "browser": { + "lz-utils": "./dist/browser.js" + }, + "exports": { + ".": { + "types": "./lib/index.d.ts", + "import": "./dist/index.mjs", + "require": "./dist/index.js", + "default": "./dist/index.js" + }, + "./compress": "./dist/compress.js", + "./decompress": "./dist/decompress.js", + "./deflate": "./dist/deflate.js", + "./deflate-sync": "./dist/deflate-sync.js", + "./inflate": "./dist/inflate.js", + "./inflate-sync": "./dist/inflate-sync.js", + "./create-script-loader": "./dist/create-script-loader.js", + "./dist/*": "./dist/*", + "./lib/*": "./lib/*", + "./package.json": "./package.json" + }, + "types": "./lib/index.d.ts", + "scripts": { + "build": "node ./scripts/build.js", + "test": "node ./scripts/test.js", + "patch": "npm run build && sf publish patch -r" + }, + "files": [ + "dist", + "lib" + ], + "keywords": [ + "lz-utils" + ], + "license": "MIT", + "dependencies": {}, + "devDependencies": { + "babel-loader": "^9.1.3", + "eight-colors": "^1.3.0", + "esbuild": "^0.23.0", + "eslint": "^9.7.0", + "eslint-config-plus": "^2.0.2", + "eslint-plugin-html": "^8.1.1", + "tiny-inflate": "^1.0.3" + } +} diff --git a/node_modules/make-dir/index.d.ts b/node_modules/make-dir/index.d.ts new file mode 100644 index 0000000..3a78251 --- /dev/null +++ b/node_modules/make-dir/index.d.ts @@ -0,0 +1,66 @@ +/// +import * as fs from 'fs'; + +declare namespace makeDir { + interface Options { + /** + Directory [permissions](https://x-team.com/blog/file-system-permissions-umask-node-js/). + + @default 0o777 + */ + readonly mode?: number; + + /** + Use a custom `fs` implementation. For example [`graceful-fs`](https://github.com/isaacs/node-graceful-fs). + + Using a custom `fs` implementation will block the use of the native `recursive` option if `fs.mkdir` or `fs.mkdirSync` is not the native function. + + @default require('fs') + */ + readonly fs?: typeof fs; + } +} + +declare const makeDir: { + /** + Make a directory and its parents if needed - Think `mkdir -p`. + + @param path - Directory to create. + @returns The path to the created directory. + + @example + ``` + import makeDir = require('make-dir'); + + (async () => { + const path = await makeDir('unicorn/rainbow/cake'); + + console.log(path); + //=> '/Users/sindresorhus/fun/unicorn/rainbow/cake' + + // Multiple directories: + const paths = await Promise.all([ + makeDir('unicorn/rainbow'), + makeDir('foo/bar') + ]); + + console.log(paths); + // [ + // '/Users/sindresorhus/fun/unicorn/rainbow', + // '/Users/sindresorhus/fun/foo/bar' + // ] + })(); + ``` + */ + (path: string, options?: makeDir.Options): Promise; + + /** + Synchronously make a directory and its parents if needed - Think `mkdir -p`. + + @param path - Directory to create. + @returns The path to the created directory. + */ + sync(path: string, options?: makeDir.Options): string; +}; + +export = makeDir; diff --git a/node_modules/make-dir/index.js b/node_modules/make-dir/index.js new file mode 100644 index 0000000..2c0814e --- /dev/null +++ b/node_modules/make-dir/index.js @@ -0,0 +1,155 @@ +'use strict'; +const fs = require('fs'); +const path = require('path'); +const {promisify} = require('util'); +const semverGte = require('semver/functions/gte'); + +const useNativeRecursiveOption = semverGte(process.version, '10.12.0'); + +// https://github.com/nodejs/node/issues/8987 +// https://github.com/libuv/libuv/pull/1088 +const checkPath = pth => { + if (process.platform === 'win32') { + const pathHasInvalidWinCharacters = /[<>:"|?*]/.test(pth.replace(path.parse(pth).root, '')); + + if (pathHasInvalidWinCharacters) { + const error = new Error(`Path contains invalid characters: ${pth}`); + error.code = 'EINVAL'; + throw error; + } + } +}; + +const processOptions = options => { + const defaults = { + mode: 0o777, + fs + }; + + return { + ...defaults, + ...options + }; +}; + +const permissionError = pth => { + // This replicates the exception of `fs.mkdir` with native the + // `recusive` option when run on an invalid drive under Windows. + const error = new Error(`operation not permitted, mkdir '${pth}'`); + error.code = 'EPERM'; + error.errno = -4048; + error.path = pth; + error.syscall = 'mkdir'; + return error; +}; + +const makeDir = async (input, options) => { + checkPath(input); + options = processOptions(options); + + const mkdir = promisify(options.fs.mkdir); + const stat = promisify(options.fs.stat); + + if (useNativeRecursiveOption && options.fs.mkdir === fs.mkdir) { + const pth = path.resolve(input); + + await mkdir(pth, { + mode: options.mode, + recursive: true + }); + + return pth; + } + + const make = async pth => { + try { + await mkdir(pth, options.mode); + + return pth; + } catch (error) { + if (error.code === 'EPERM') { + throw error; + } + + if (error.code === 'ENOENT') { + if (path.dirname(pth) === pth) { + throw permissionError(pth); + } + + if (error.message.includes('null bytes')) { + throw error; + } + + await make(path.dirname(pth)); + + return make(pth); + } + + try { + const stats = await stat(pth); + if (!stats.isDirectory()) { + throw new Error('The path is not a directory'); + } + } catch { + throw error; + } + + return pth; + } + }; + + return make(path.resolve(input)); +}; + +module.exports = makeDir; + +module.exports.sync = (input, options) => { + checkPath(input); + options = processOptions(options); + + if (useNativeRecursiveOption && options.fs.mkdirSync === fs.mkdirSync) { + const pth = path.resolve(input); + + fs.mkdirSync(pth, { + mode: options.mode, + recursive: true + }); + + return pth; + } + + const make = pth => { + try { + options.fs.mkdirSync(pth, options.mode); + } catch (error) { + if (error.code === 'EPERM') { + throw error; + } + + if (error.code === 'ENOENT') { + if (path.dirname(pth) === pth) { + throw permissionError(pth); + } + + if (error.message.includes('null bytes')) { + throw error; + } + + make(path.dirname(pth)); + return make(pth); + } + + try { + if (!options.fs.statSync(pth).isDirectory()) { + throw new Error('The path is not a directory'); + } + } catch { + throw error; + } + } + + return pth; + }; + + return make(path.resolve(input)); +}; diff --git a/node_modules/make-dir/license b/node_modules/make-dir/license new file mode 100644 index 0000000..fa7ceba --- /dev/null +++ b/node_modules/make-dir/license @@ -0,0 +1,9 @@ +MIT License + +Copyright (c) Sindre Sorhus (https://sindresorhus.com) + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/node_modules/make-dir/package.json b/node_modules/make-dir/package.json new file mode 100644 index 0000000..db305b1 --- /dev/null +++ b/node_modules/make-dir/package.json @@ -0,0 +1,63 @@ +{ + "name": "make-dir", + "version": "4.0.0", + "description": "Make a directory and its parents if needed - Think `mkdir -p`", + "license": "MIT", + "repository": "sindresorhus/make-dir", + "funding": "https://github.com/sponsors/sindresorhus", + "author": { + "name": "Sindre Sorhus", + "email": "sindresorhus@gmail.com", + "url": "https://sindresorhus.com" + }, + "engines": { + "node": ">=10" + }, + "scripts": { + "test": "xo && nyc ava && tsd" + }, + "files": [ + "index.js", + "index.d.ts" + ], + "keywords": [ + "mkdir", + "mkdirp", + "make", + "directories", + "folders", + "directory", + "folder", + "path", + "parent", + "parents", + "intermediate", + "recursively", + "recursive", + "create", + "fs", + "filesystem", + "file-system" + ], + "dependencies": { + "semver": "^7.5.3" + }, + "devDependencies": { + "@types/graceful-fs": "^4.1.3", + "@types/node": "^14.14.6", + "ava": "^2.4.0", + "codecov": "^3.2.0", + "graceful-fs": "^4.1.15", + "nyc": "^15.0.0", + "path-type": "^4.0.0", + "tempy": "^1.0.0", + "tsd": "^0.13.1", + "xo": "^0.34.2" + }, + "nyc": { + "reporter": [ + "text", + "lcov" + ] + } +} diff --git a/node_modules/make-dir/readme.md b/node_modules/make-dir/readme.md new file mode 100644 index 0000000..13fa8fd --- /dev/null +++ b/node_modules/make-dir/readme.md @@ -0,0 +1,125 @@ +# make-dir [![codecov](https://codecov.io/gh/sindresorhus/make-dir/branch/main/graph/badge.svg)](https://codecov.io/gh/sindresorhus/make-dir) + +> Make a directory and its parents if needed - Think `mkdir -p` + +## Advantages over [`mkdirp`](https://github.com/substack/node-mkdirp) + +- Promise API *(Async/await ready!)* +- Fixes many `mkdirp` issues: [#96](https://github.com/substack/node-mkdirp/pull/96) [#70](https://github.com/substack/node-mkdirp/issues/70) [#66](https://github.com/substack/node-mkdirp/issues/66) +- 100% test coverage +- CI-tested on macOS, Linux, and Windows +- Actively maintained +- Doesn't bundle a CLI +- Uses the native `fs.mkdir/mkdirSync` [`recursive` option](https://nodejs.org/dist/latest/docs/api/fs.html#fs_fs_mkdir_path_options_callback) in Node.js >=10.12.0 unless [overridden](#fs) + +## Install + +``` +$ npm install make-dir +``` + +## Usage + +``` +$ pwd +/Users/sindresorhus/fun +$ tree +. +``` + +```js +const makeDir = require('make-dir'); + +(async () => { + const path = await makeDir('unicorn/rainbow/cake'); + + console.log(path); + //=> '/Users/sindresorhus/fun/unicorn/rainbow/cake' +})(); +``` + +``` +$ tree +. +└── unicorn + └── rainbow + └── cake +``` + +Multiple directories: + +```js +const makeDir = require('make-dir'); + +(async () => { + const paths = await Promise.all([ + makeDir('unicorn/rainbow'), + makeDir('foo/bar') + ]); + + console.log(paths); + /* + [ + '/Users/sindresorhus/fun/unicorn/rainbow', + '/Users/sindresorhus/fun/foo/bar' + ] + */ +})(); +``` + +## API + +### makeDir(path, options?) + +Returns a `Promise` for the path to the created directory. + +### makeDir.sync(path, options?) + +Returns the path to the created directory. + +#### path + +Type: `string` + +Directory to create. + +#### options + +Type: `object` + +##### mode + +Type: `integer`\ +Default: `0o777` + +Directory [permissions](https://x-team.com/blog/file-system-permissions-umask-node-js/). + +##### fs + +Type: `object`\ +Default: `require('fs')` + +Use a custom `fs` implementation. For example [`graceful-fs`](https://github.com/isaacs/node-graceful-fs). + +Using a custom `fs` implementation will block the use of the native `recursive` option if `fs.mkdir` or `fs.mkdirSync` is not the native function. + +## Related + +- [make-dir-cli](https://github.com/sindresorhus/make-dir-cli) - CLI for this module +- [del](https://github.com/sindresorhus/del) - Delete files and directories +- [globby](https://github.com/sindresorhus/globby) - User-friendly glob matching +- [cpy](https://github.com/sindresorhus/cpy) - Copy files +- [cpy-cli](https://github.com/sindresorhus/cpy-cli) - Copy files on the command-line +- [move-file](https://github.com/sindresorhus/move-file) - Move a file + +--- + +
+ + Get professional support for this package with a Tidelift subscription + +
+ + Tidelift helps make open source sustainable for maintainers while giving companies
assurances about security, maintenance, and licensing for their dependencies. +
+
diff --git a/node_modules/monocart-coverage-reports/LICENSE b/node_modules/monocart-coverage-reports/LICENSE new file mode 100644 index 0000000..513af51 --- /dev/null +++ b/node_modules/monocart-coverage-reports/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2023 cenfun + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/node_modules/monocart-coverage-reports/README.md b/node_modules/monocart-coverage-reports/README.md new file mode 100644 index 0000000..be9db15 --- /dev/null +++ b/node_modules/monocart-coverage-reports/README.md @@ -0,0 +1,1186 @@ +# Monocart Coverage Reports + +[![npm](https://img.shields.io/npm/v/monocart-coverage-reports)](https://www.npmjs.com/package/monocart-coverage-reports) +![license](https://img.shields.io/github/license/cenfun/monocart-coverage-reports) +![build](https://img.shields.io/github/actions/workflow/status/cenfun/monocart-coverage-reports/ci.yml) +[![install size](https://packagephobia.com/badge?p=monocart-coverage-reports)](https://packagephobia.com/result?p=monocart-coverage-reports) +[![npm graph](https://img.shields.io/badge/npm-graph-blue)](https://npmgraph.js.org/?q=monocart-coverage-reports) +![dependencies](https://img.shields.io/librariesio/github/cenfun/monocart-coverage-reports) +[![downloads](https://devimg.vercel.app/npm/downloads/monocart-coverage-reports?label={total}%20downloads/month)](https://www.npmjs.com/package/monocart-coverage-reports) + +🌐 English | [简体中文](README.zh-Hans.md) + +> A JavaScript code coverage tool to generate native [V8](https://v8.dev/blog/javascript-code-coverage) reports or [Istanbul](https://istanbul.js.org/) reports. + +* [Usage](#usage) +* [Options](#options) +* [Available Reports](#available-reports) +* [Compare Reports](#compare-reports) +* [Collecting Istanbul Coverage Data](#collecting-istanbul-coverage-data) +* [Collecting V8 Coverage Data](#collecting-v8-coverage-data) + - [Collecting V8 Coverage Data with Playwright](#collecting-v8-coverage-data-with-playwright) + - [Collecting Raw V8 Coverage Data with Puppeteer](#collecting-raw-v8-coverage-data-with-puppeteer) + - [Collecting V8 Coverage Data from Node.js](#collecting-v8-coverage-data-from-nodejs) + - [Collecting V8 Coverage Data with `CDPClient` API](#collecting-v8-coverage-data-with-cdpclient-api) + - [V8 Coverage Data API](#v8-coverage-data-api) +* [Filtering Results](#filtering-results) +* [Resolve `sourcePath` for the Source Files](#resolve-sourcepath-for-the-source-files) +* [Adding Empty Coverage for Untested Files](#adding-empty-coverage-for-untested-files) +* [onEnd Hook](#onend-hook) +* [Ignoring Uncovered Codes](#ignoring-uncovered-codes) +* [Multiprocessing Support](#multiprocessing-support) +* [Command Line](#command-line) +* [Config File](#config-file) +* [Merge Coverage Reports](#merge-coverage-reports) + - [Automatic Merging](#automatic-merging) + - [Manual Merging](#manual-merging) +* [Common issues](#common-issues) + - [Unexpected coverage](#unexpected-coverage) + - [Unparsable source](#unparsable-source) + - [JavaScript heap out of memory](#javascript-heap-out-of-memory) +* [Debug for Coverage and Sourcemap](#debug-for-coverage-and-sourcemap) +* [Integration with Any Testing Framework](#integration-with-any-testing-framework) +* [Integration Examples](#integration-examples) + - [Playwright](#playwright) + - [c8](#c8) + - [CodeceptJS](#codeceptjs) + - [VSCode](#vscode) + - [Jest](#jest) + - [Vitest](#vitest) + - [Node Test Runner](#node-test-runner) + - [Puppeteer](#puppeteer) + - [Cypress](#cypress) + - [WebdriverIO](#webdriverio) + - [Storybook Test Runner](#storybook-test-runner) + - [TestCafe](#testcafe) + - [Selenium Webdriver](#selenium-webdriver) + - [Mocha](#mocha) + - [TypeScript](#typescript) + - [AVA](#ava) + - [Codecov](#codecov) + - [Codacy](#codacy) + - [Coveralls](#coveralls) + - [Sonar Cloud](#sonar-cloud) +* [Contributing](#contributing) +* [Changelog](CHANGELOG.md) +* [Thanks](#thanks) + +## Usage +> It's recommended to use [Node.js 20+](https://nodejs.org/). +- Install +```sh +npm install monocart-coverage-reports +``` +- API +```js +const MCR = require('monocart-coverage-reports'); +const mcr = MCR({ + name: 'My Coverage Report - 2024-02-28', + outputDir: './coverage-reports', + reports: ["v8", "console-details"], + cleanCache: true +}); +await mcr.add(coverageData); +await mcr.generate(); +``` +Using `import` and load options from [config file](#config-file) +```js +import { CoverageReport } from 'monocart-coverage-reports'; +const mcr = new CoverageReport(); +await mcr.loadConfig(); +``` +For more information, see [Multiprocessing Support](#multiprocessing-support) + +- CLI +```sh +mcr node my-app.js -r v8,console-details +``` +For more information, see [Command Line](#command-line) + +## Options +- Default options: [lib/default/options.js](./lib/default/options.js) +- Options declaration see `CoverageReportOptions` [lib/index.d.ts](./lib/index.d.ts) +- [Config file](#config-file) + +## Available Reports + +> V8 build-in reports (V8 data only): + +- `v8` + - Features: + - A Brand-New V8 Coverage Report User Interface + - Support for Native Byte Statistics + - Support processing big data with high performance + - Coverage for Any Runtime Code + - CSS Coverage Support + - Better Support for Sourcemap Conversion + - Demos: [V8](https://cenfun.github.io/monocart-coverage-reports/v8) and [more](https://cenfun.github.io/monocart-coverage-reports/) + +![](./assets/v8.gif) + +- `v8-json` + - Save `CoverageResults` to a json file (defaults to [`coverage-report.json`](https://cenfun.github.io/monocart-coverage-reports/v8-and-istanbul/coverage-report.json)). + - Shows native V8 code coverage with VSCode extension: [Monocart Coverage for VSCode](https://github.com/cenfun/monocart-coverage-vscode) + +![](./assets/mcv.gif) + +> Istanbul build-in reports (both V8 and Istanbul data): + +- `clover` +- `cobertura` +- `html` + - [Istanbul html](https://cenfun.github.io/monocart-coverage-reports/istanbul/) + - [V8 to Istanbul](https://cenfun.github.io/monocart-coverage-reports/v8-and-istanbul/istanbul) +- `html-spa` +- `json` +- `json-summary` +- `lcov` +- `lcovonly` + - [V8 lcov.info](https://cenfun.github.io/monocart-coverage-reports/v8/lcov.info) + - [Istanbul lcov.info](https://cenfun.github.io/monocart-coverage-reports/istanbul/lcov.info) +- `none` +- `teamcity` +- `text` +- `text-lcov` +- `text-summary` + +> Other build-in reports (both V8 and Istanbul data): + +- `codecov` Save coverage data to a json file with [Codecov](https://docs.codecov.com/docs/codecov-custom-coverage-format) format (defaults to `codecov.json`), see [example](https://app.codecov.io/github/cenfun/monocart-coverage-reports). + +- `codacy` Save coverage data to a json file with [Codacy API](https://api.codacy.com/swagger#tocscoveragereport) format (defaults to `codacy.json`). + +- `console-summary` shows coverage summary in the console. + +![](./assets/console-summary.png) + +- `console-details` Show coverage details in the console. Like `text`, but for V8. For Github actions, we can enforce color with env: `FORCE_COLOR: true`. + +![](./assets/console-details.png) + +- `markdown-summary` Save coverage summary to a markdown file (defaults to `coverage-summary.md`). For Github actions, we can show the markdown content to [a job summary](https://docs.github.com/en/actions/using-workflows/workflow-commands-for-github-actions#adding-a-job-summary) +```sh +cat path-to/coverage-summary.md >> $GITHUB_STEP_SUMMARY +``` +![](./assets/markdown-summary.png) + +- `markdown-details` Save coverage details to a markdown file (defaults to `coverage-details.md`). + - Preview in [runs](https://github.com/cenfun/monocart-coverage-reports/actions/workflows/ci.yml) + +- `raw` only keep all original data, which can be used for other reports input with `inputDir`. see [Merge Coverage Reports](#merge-coverage-reports) + +- Custom Reporter + ```js + { + reports: [ + [path.resolve('./test/custom-istanbul-reporter.js'), { + type: 'istanbul', + file: 'custom-istanbul-coverage.text' + }], + [path.resolve('./test/custom-v8-reporter.js'), { + type: 'v8', + outputFile: 'custom-v8-coverage.json' + }], + [path.resolve('./test/custom-v8-reporter.mjs'), { + type: 'both' + }] + ] + } + ``` + - Istanbul custom reporter + > example: [./test/custom-istanbul-reporter.js](./test/custom-istanbul-reporter.js), see [istanbul built-in reporters' implementation](https://github.com/istanbuljs/istanbuljs/tree/master/packages/istanbul-reports/lib) for reference. + - V8 custom reporter + > example: [./test/custom-v8-reporter.js](./test/custom-v8-reporter.js) + +### Multiple Reports: +```js +const MCR = require('monocart-coverage-reports'); +const coverageOptions = { + outputDir: './coverage-reports', + reports: [ + // build-in reports + ['console-summary'], + ['v8'], + ['html', { + subdir: 'istanbul' + }], + ['json', { + file: 'my-json-file.json' + }], + 'lcovonly', + + // custom reports + // Specify reporter name with the NPM package + ["custom-reporter-1"], + ["custom-reporter-2", { + type: "istanbul", + key: "value" + }], + // Specify reporter name with local path + ['/absolute/path/to/custom-reporter.js'] + ] +} +const mcr = MCR(coverageOptions); +``` + +## Compare Reports +> If the V8 data format is used for Istanbul reports, it will be automatically converted from V8 to Istanbul. + +| | Istanbul | V8 | V8 to Istanbul | +| :--------------| :------ | :------ | :---------------------- | +| Coverage data | [Istanbul](https://github.com/gotwarlost/istanbul/blob/master/coverage.json.md) (Object) | [V8](#v8-coverage-data-format) (Array) | [V8](#v8-coverage-data-format) (Array) | +| Output | [Istanbul reports](#available-reports) | [V8 reports](#available-reports) | [Istanbul reports](#available-reports) | +| - Bytes | ❌ | ✅ | ❌ | +| - Statements | ✅ | ✅ | ✅ | +| - Branches | ✅ | ✅ | ✅ | +| - Functions | ✅ | ✅ | ✅ | +| - Lines | ✅ | ✅ | ✅ | +| - Execution counts | ✅ | ✅ | ✅ | +| CSS coverage | ❌ | ✅ | ✅ | +| Minified code | ❌ | ✅ | ❌ | + +## Collecting Istanbul Coverage Data +- Before coverage collection: Instrumenting source code with Istanbul + - webpack with babel loader: [babel-plugin-istanbul](https://github.com/istanbuljs/babel-plugin-istanbul), see example: [webpack.config-istanbul.js](./test/build/webpack.config-istanbul.js) + - CLI: [nyc instrument](https://github.com/istanbuljs/nyc/blob/master/docs/instrument.md) or API: [istanbul-lib-instrument](https://github.com/istanbuljs/istanbuljs/blob/main/packages/istanbul-lib-instrument/api.md) + - vite: [vite-plugin-istanbul](https://github.com/ifaxity/vite-plugin-istanbul) + - rollup: [rollup-plugin-istanbul](https://github.com/artberri/rollup-plugin-istanbul) + - swc: [swc-plugin-coverage-instrument](https://github.com/kwonoj/swc-plugin-coverage-instrument) + +- Browser + - Collecting coverage data from `window.__coverage__`, example: [test-istanbul.js](./test/test-istanbul.js) + +- Node.js + - Collecting coverage data from `global.__coverage__` + +- CDP + - `getIstanbulCoverage()` see [`CDPClient` API](#collecting-v8-coverage-data-with-cdpclient-api) + +## Collecting V8 Coverage Data +- Before coverage collection: Enabling `sourcemap` for source code + - [webpack](https://webpack.js.org/configuration/): `devtool: source-map` and `mode: development`, example [webpack.config-v8.js](./test/build/webpack.config-v8.js) + - [rollup](https://rollupjs.org/configuration-options/): `sourcemap: true` and `treeshake: false` + - [esbuild](https://esbuild.github.io/api/): `sourcemap: true`, `treeShaking: false` and `minify: false` + - [vite](https://vitejs.dev/config/build-options.html): `sourcemap: true` and `minify: false` + +- Browser (Chromium-based Only) + - [Collecting V8 Coverage Data with Playwright](#collecting-v8-coverage-data-with-playwright) + - [Collecting Raw V8 Coverage Data with Puppeteer](#collecting-raw-v8-coverage-data-with-puppeteer) + +- Node.js + - [Collecting V8 Coverage Data from Node.js](#collecting-v8-coverage-data-from-nodejs) + +- CDP + - [Collecting V8 Coverage Data with `CDPClient` API](#collecting-v8-coverage-data-with-cdpclient-api) + +### Collecting V8 Coverage Data with Playwright +```js +await Promise.all([ + page.coverage.startJSCoverage({ + // reportAnonymousScripts: true, + resetOnNavigation: false + }), + page.coverage.startCSSCoverage({ + // Note, anonymous styles (without sourceURLs) are not supported, alternatively, you can use CDPClient + resetOnNavigation: false + }) +]); + +await page.goto("your page url"); + +const [jsCoverage, cssCoverage] = await Promise.all([ + page.coverage.stopJSCoverage(), + page.coverage.stopCSSCoverage() +]); + +const coverageData = [... jsCoverage, ... cssCoverage]; + +``` +Collect coverage with `@playwright/test` [`Automatic fixtures`](https://playwright.dev/docs/test-fixtures#automatic-fixtures), see example: [fixtures.ts](https://github.com/cenfun/playwright-coverage/blob/main/fixtures.ts) +For more examples, see [./test/test-v8.js](./test/test-v8.js), [css](./test/test-css.js) + + +### Collecting Raw V8 Coverage Data with Puppeteer +```js +await Promise.all([ + page.coverage.startJSCoverage({ + // reportAnonymousScripts: true, + resetOnNavigation: false, + // provide raw v8 coverage data + includeRawScriptCoverage: true + }), + page.coverage.startCSSCoverage({ + resetOnNavigation: false + }) +]); + +await page.goto("your page url"); + +const [jsCoverage, cssCoverage] = await Promise.all([ + page.coverage.stopJSCoverage(), + page.coverage.stopCSSCoverage() +]); + +// to raw V8 script coverage +const coverageData = [... jsCoverage.map((it) => { + return { + source: it.text, + ... it.rawScriptCoverage + }; +}), ... cssCoverage]; +``` +Example: [./test/test-puppeteer.js](./test/test-puppeteer.js) + +### Collecting V8 Coverage Data from Node.js +Possible solutions: +- [NODE_V8_COVERAGE](https://nodejs.org/docs/latest/api/cli.html#node_v8_coveragedir)=`dir` + - Sets Node.js env `NODE_V8_COVERAGE`=`dir` before the program running, the coverage data will be saved to the `dir` after the program exits gracefully. + - Read the JSON file(s) from the `dir` and generate coverage report. + - Example: + > cross-env NODE_V8_COVERAGE=`.temp/v8-coverage-env` node [./test/test-node-env.js](./test/test-node-env.js) && node [./test/generate-report.js](./test/generate-report.js) + +- [V8](https://nodejs.org/docs/latest/api/v8.html#v8takecoverage) API + NODE_V8_COVERAGE + - Writing the coverage started by NODE_V8_COVERAGE to disk on demand with `v8.takeCoverage()`, it does not require waiting until the program exits gracefully. + - Example: + > cross-env NODE_V8_COVERAGE=`.temp/v8-coverage-api` node [./test/test-node-api.js](./test/test-node-api.js) + +- [Inspector](https://nodejs.org/docs/latest/api/inspector.html) API + - Connecting to the V8 inspector and enable V8 coverage. + - Taking coverage data and adding it to the report. + - Example: + > node [./test/test-node-ins.js](./test/test-node-ins.js) + - vm Example (scriptOffset): + > node [./test/test-node-vm.js](./test/test-node-vm.js) + +- [CDP](https://chromedevtools.github.io/devtools-protocol/) API + - Enabling [Node Debugging](https://nodejs.org/en/guides/debugging-getting-started/). + - Collecting coverage data with CDP API. + - Example: + > node --inspect=9229 [./test/test-node-cdp.js](./test/test-node-cdp.js) + +- [Node Debugging](https://nodejs.org/en/guides/debugging-getting-started) + CDP + NODE_V8_COVERAGE + V8 API + - When the program starts a server, it will not exit on its own, thus requiring a manual invocation of the `v8.takeCoverage()` interface to manually collect coverage data. Remote invocation of the `v8.takeCoverage()` interface can be accomplished through the `Runtime.evaluate` of the CDP. + - Example for [koa](https://github.com/koajs/koa) web server: + > node [./test/test-node-koa.js](./test/test-node-koa.js) + +- [Child Process](https://nodejs.org/docs/latest/api/child_process.html) + NODE_V8_COVERAGE + - see [Command Line](#command-line) + +### Collecting V8 Coverage Data with `CDPClient` API +- `CDPClient` available APIs +```js +startJSCoverage: () => Promise; +stopJSCoverage: () => Promise; + +startCSSCoverage: () => Promise; +stopCSSCoverage: () => Promise; + +/** start both js and css coverage */ +startCoverage: () => Promise; +/** stop and return both js and css coverage */ +stopCoverage: () => Promise; + +/** write the coverage started by NODE_V8_COVERAGE to disk on demand, returns v8 coverage dir */ +writeCoverage: () => Promise; + +/** get istanbul coverage data */ +getIstanbulCoverage: (coverageKey?: string) => Promise; +``` + +- Work with node debugger port `--inspect=9229` or browser debugging port `--remote-debugging-port=9229` +```js +const MCR = require('monocart-coverage-reports'); +const client = await MCR.CDPClient({ + port: 9229 +}); +await client.startJSCoverage(); +// run your test here +const coverageData = await client.stopJSCoverage(); +``` + +- Work with [Playwright CDPSession](https://playwright.dev/docs/api/class-cdpsession) +```js +const { chromium } = require('playwright'); +const MCR = require('monocart-coverage-reports'); +const browser = await chromium.launch(); +const page = await browser.newPage(); +const session = await page.context().newCDPSession(page); +const client = await MCR.CDPClient({ + session +}); +// both js and css coverage +await client.startCoverage(); +// run your test page here +await page.goto("your page url"); +const coverageData = await client.stopCoverage(); +``` + +- Work with [Puppeteer CDPSession](https://pptr.dev/api/puppeteer.cdpsession) +```js +const puppeteer = require('puppeteer'); +const MCR = require('monocart-coverage-reports'); +const browser = await puppeteer.launch({}); +const page = await browser.newPage(); +const session = await page.target().createCDPSession(); +const client = await MCR.CDPClient({ + session +}); +// both js and css coverage +await client.startCoverage(); +// run your test page here +await page.goto("your page url"); +const coverageData = await client.stopCoverage(); +``` + +- Work with [Selenium Webdriver](https://www.selenium.dev/documentation/webdriver/) WebSocket (Chrome/Edge Browser) +```js +const { Builder, Browser } = require('selenium-webdriver'); +const MCR = require('monocart-coverage-reports'); +const driver = await new Builder().forBrowser(Browser.CHROME).build(); +const pageCdpConnection = await driver.createCDPConnection('page'); +const session = new MCR.WSSession(pageCdpConnection._wsConnection); +const client = await MCR.CDPClient({ + session +}) +``` + +### V8 Coverage Data API +- [JavaScript code coverage in V8](https://v8.dev/blog/javascript-code-coverage) +- [Playwright Coverage Class](https://playwright.dev/docs/api/class-coverage) +- [Puppeteer Coverage Class](https://pptr.dev/api/puppeteer.coverage) +- [DevTools Protocol for Coverage](https://chromedevtools.github.io/devtools-protocol/tot/Profiler/#method-startPreciseCoverage) see [ScriptCoverage](https://chromedevtools.github.io/devtools-protocol/tot/Profiler/#type-ScriptCoverage) and [v8-coverage](https://github.com/bcoe/v8-coverage) +```js +// Coverage data for a source range. +export interface CoverageRange { + // JavaScript script source offset for the range start. + startOffset: integer; + // JavaScript script source offset for the range end. + endOffset: integer; + // Collected execution count of the source range. + count: integer; +} +// Coverage data for a JavaScript function. +/** + * @functionName can be an empty string. + * @ranges is always non-empty. The first range is called the "root range". + * @isBlockCoverage indicates if the function has block coverage information. + If this is false, it usually means that the functions was never called. + It seems to be equivalent to ranges.length === 1 && ranges[0].count === 0. +*/ +export interface FunctionCoverage { + // JavaScript function name. + functionName: string; + // Source ranges inside the function with coverage data. + ranges: CoverageRange[]; + // Whether coverage data for this function has block granularity. + isBlockCoverage: boolean; +} +// Coverage data for a JavaScript script. +export interface ScriptCoverage { + // JavaScript script id. + scriptId: Runtime.ScriptId; + // JavaScript script name or url. + url: string; + // Functions contained in the script that has coverage data. + functions: FunctionCoverage[]; +} +export type V8CoverageData = ScriptCoverage[]; +``` + +| JavaScript Runtime | V8 Coverage | | +| :--------------| :----: | :---------------------- | +| Chrome (65%) | ✅ | Chromium-based | +| Safari (18%) | ❌ | | +| Edge (5%) | ✅ | Chromium-based | +| Firefox (2%) | ❌ | | +| Node.js | ✅ | | +| Deno | ❌ | [issue](https://github.com/denoland/deno/issues/23359) | +| Bun | ❌ | | + +## Filtering Results +### Using `entryFilter` and `sourceFilter` to filter the results for V8 report +When V8 coverage data collected, it actually contains the data of all entry files, for example: + +- *dist/main.js* +- *dist/vendor.js* +- *dist/something-else.js* + +We can use `entryFilter` to filter the entry files. For example, we should remove `vendor.js` and `something-else.js` if they are not in our coverage scope. + +- *dist/main.js* + +When inline or linked sourcemap exists to the entry file, the source files will be extracted from the sourcemap for the entry file, and the entry file will be removed if `logging` is not `debug`. + +- *src/index.js* +- *src/components/app.js* +- *node_modules/dependency/dist/dependency.js* + +We can use `sourceFilter` to filter the source files. For example, we should remove `dependency.js` if it is not in our coverage scope. + +- *src/index.js* +- *src/components/app.js* + +For example: +```js +const coverageOptions = { + entryFilter: (entry) => entry.url.indexOf("main.js") !== -1, + sourceFilter: (sourcePath) => sourcePath.search(/src\//) !== -1 +}; +``` +Or using [`minimatch`](https://github.com/isaacs/minimatch) pattern: +```js +const coverageOptions = { + entryFilter: "**/main.js", + sourceFilter: "**/src/**" +}; +``` +Support multiple patterns: +```js +const coverageOptions = { + entryFilter: { + '**/node_modules/**': false, + '**/vendor.js': false, + '**/src/**': true + }, + sourceFilter: { + '**/node_modules/**': false, + '**/**': true + } +}; +``` +As CLI args (JSON-like string. Added in: v2.8): +```sh +mcr --sourceFilter "{'**/node_modules/**':false,'**/**':true}" +``` +Note, those patterns will be transformed to a function, and the order of the patterns will impact the results: +```js +const coverageOptions = { + entryFilter: (entry) => { + if (minimatch(entry.url, '**/node_modules/**')) { return false; } + if (minimatch(entry.url, '**/vendor.js')) { return false; } + if (minimatch(entry.url, '**/src/**')) { return true; } + return false; // else unmatched + } +}; +``` + +### Using `filter` instead of `entryFilter` and `sourceFilter` +If you don't want to define both `entryFilter` and `sourceFilter`, you can use `filter` instead. (Added in: v2.8) +```js +const coverageOptions = { + // combined patterns + filter: { + '**/node_modules/**': false, + '**/vendor.js': false, + '**/src/**': true + '**/**': true + } +}; +``` + +## Resolve `sourcePath` for the Source Files +If the source file comes from the sourcemap, then its path is a virtual path. Using the `sourcePath` option to resolve a custom path. +For example, we have tested multiple dist files, which contain some common files. We hope to merge the coverage of the same files, so we need to unify the `sourcePath` in order to be able to merge the coverage data. +```js +const coverageOptions = { + sourcePath: (filePath) => { + // Remove the virtual prefix + const list = ['my-dist-file1/', 'my-dist-file2/']; + for (const str of list) { + if (filePath.startsWith(str)) { + return filePath.slice(str.length); + } + } + return filePath; + } +}; +``` +It also supports simple key/value replacement: +```js +const coverageOptions = { + sourcePath: { + 'my-dist-file1/': '', + 'my-dist-file2/': '' + } +}; +``` +Normalize the full path of the file: +```js +const path = require("path") + +// MCR coverage options +const coverageOptions = { + sourcePath: (filePath, info)=> { + if (!filePath.includes('/') && info.distFile) { + return `${path.dirname(info.distFile)}/${filePath}`; + } + return filePath; + } +} +``` + +## Adding Empty Coverage for Untested Files +By default the untested files will not be included in the coverage report, we can add empty coverage for untested files with option `all`, the untested files will show 0% coverage. +```js +const coverageOptions = { + all: './src', + + // or multiple dirs + all: ['./src', './lib'], +}; +``` +The untested files will apply to the `sourceFilter`. And it also supports additional `filter` (return the file type for js or css coverage): +```js +const coverageOptions = { + all: { + dir: ['./src'], + filter: { + // exclude files + '**/ignored-*.js': false, + '**/*.html': false, + // empty css coverage + '**/*.scss': "css", + '**/*': true + } + } +}; +``` +We can also compile these untested files, such as .ts, .jsx, or .vue, etc., so that they can be analyzed by the default AST parser, thus get more coverage metric data. +```js +const path = require("path"); +const swc = require("@swc/core"); +const coverageOptions = { + all: { + dir: ['./src'], + transformer: async (entry) => { + const { code, map } = await swc.transform(entry.source, { + filename: path.basename(entry.url), + sourceMaps: true, + isModule: true, + jsc: { + parser: { + syntax: "typescript", + jsx: true + }, + transform: {} + } + }); + entry.source = code; + entry.sourceMap = JSON.parse(map); + } + } +}; +``` + +## onEnd Hook +For example, checking thresholds: +```js +const EC = require('eight-colors'); +const coverageOptions = { + name: 'My Coverage Report', + outputDir: './coverage-reports', + onEnd: (coverageResults) => { + const thresholds = { + bytes: 80, + lines: 60 + }; + console.log('check thresholds ...', thresholds); + const errors = []; + const { summary } = coverageResults; + Object.keys(thresholds).forEach((k) => { + const pct = summary[k].pct; + if (pct < thresholds[k]) { + errors.push(`Coverage threshold for ${k} (${pct} %) not met: ${thresholds[k]} %`); + } + }); + if (errors.length) { + const errMsg = errors.join('\n'); + console.log(EC.red(errMsg)); + // throw new Error(errMsg); + // process.exit(1); + } + } +} +``` + +## Ignoring Uncovered Codes +To ignore codes, use the special comment which starts with `v8 ignore `: +- Ignoring all until stop +```js +/* v8 ignore start */ +function uncovered() { +} +/* v8 ignore stop */ +``` +- Ignoring the next line or next N lines +```js +/* v8 ignore next */ +const os = platform === 'wind32' ? 'Windows' : 'Other'; + +const os = platform === 'wind32' ? 'Windows' /* v8 ignore next */ : 'Other'; + +// v8 ignore next 3 +if (platform === 'linux') { + console.log('hello linux'); +} +``` +- Compatible with [c8 coverage](https://github.com/bcoe/c8/?tab=readme-ov-file#ignoring-all-lines-until-told) or [nodejs coverage](https://nodejs.org/docs/latest/api/test.html#collecting-code-coverage) syntax +```js +/* c8 ignore start */ +function uncovered() { +} +/* c8 ignore stop */ + +/* node:coverage disable */ +function uncovered() { +} +/* node:coverage enable */ +``` + +## Multiprocessing Support +> The data will be added to `[outputDir]/.cache`, After the generation of the report, this data will be removed unless debugging has been enabled or a raw report has been used, see [Debug for Coverage and Sourcemap](#debug-for-coverage-and-sourcemap) +- Main process, before the start of testing +```js +const MCR = require('monocart-coverage-reports'); +const coverageOptions = require('path-to/same-options.js'); +const mcr = MCR(coverageOptions); +// clean previous cache before the start of testing +// unless the running environment is new and no cache +mcr.cleanCache(); +``` + +- Sub process 1, testing stage 1 +```js +const MCR = require('monocart-coverage-reports'); +const coverageOptions = require('path-to/same-options.js'); +const mcr = MCR(coverageOptions); +await mcr.add(coverageData1); +``` + +- Sub process 2, testing stage 2 +```js +const MCR = require('monocart-coverage-reports'); +const coverageOptions = require('path-to/same-options.js'); +const mcr = MCR(coverageOptions); +await mcr.add(coverageData2); +``` + +- Main process, after the completion of testing +```js +// generate coverage reports after the completion of testing +const MCR = require('monocart-coverage-reports'); +const coverageOptions = require('path-to/same-options.js'); +const mcr = MCR(coverageOptions); +await mcr.generate(); +``` + +## Command Line +> The CLI will run the program as a [child process](https://nodejs.org/docs/latest/api/child_process.html) with `NODE_V8_COVERAGE=dir` until it exits gracefully, and generate the coverage report with the coverage data from the `dir`. + +- Installing globally +```sh +npm i monocart-coverage-reports -g +mcr node ./test/specs/node.test.js -r v8,console-details --lcov +``` + +- Locally in your project +```sh +npm i monocart-coverage-reports +npx mcr node ./test/specs/node.test.js -r v8,console-details --lcov +``` + +- CLI Options +see all options with running `mcr` or `mcr --help` + +- Use `--` to separate sub CLI args +```sh +mcr -c mcr.config.js -- sub-cli -c sub-cli.config.js +``` + +- Examples + - [Mocha](#mocha) + - [TypeScript](#typescript) + - [AVA](#ava) + +## Config File +Loading config file by priority: +- Custom config file: + - CLI: `mcr --config ` + - API: `await mcr.loadConfig("my-config-file-path")` +- `mcr.config.js` +- `mcr.config.cjs` +- `mcr.config.mjs` +- `mcr.config.json` - json format +- `mcr.config.ts` (requires preloading the ts execution module) + +## Merge Coverage Reports +The following usage scenarios may require merging coverage reports: +- When the code is executed in different environments, like Node.js `server side` and browser `client side` (`Next.js` for instance). Each environment may generate its own coverage report. Merging them can give a more comprehensive view of the test coverage. +- When the code is subjected to different kinds of testing. For example, `unit tests` with `Jest` might cover certain parts of the code, while `end-to-end tests` with `Playwright` might cover other parts. Merging these different coverage reports can provide a holistic view of what code has been tested. +- When tests are run on different machines or containers, each might produce its own coverage report. Merging these can give a complete picture of the test coverage across all machines or shards. + +### Automatic Merging +- The `MCR` will automatically merge all the added coverage data when executing `generate()`. And it supports adding coverage data asynchronously across processes, see [Multiprocessing Support](#multiprocessing-support) +- For `Next.js`, it can actually add coverage data including both server side and client side before executing `generate()`, see example [nextjs-with-playwright](https://github.com/cenfun/nextjs-with-playwright) +- Using `Codecov`, a popular online code coverage service, which supports automatic merging of reports. Please use report `codecov`, it will generate report file `codecov.json`. If multiple `codecov.json` files are generated, upload all these files, they will be automatically merged. see [Codecov](#codecov) and [merging reports](https://docs.codecov.com/docs/merging-reports) + +### Manual Merging +If the reports cannot be merged automatically, then here is how to manually merge the reports. +First, using the `raw` report to export the original coverage data to the specified directory. +- For example, we have `raw` coverage data from `unit test`, which is output to `./coverage-reports/unit/raw`. Unit test examples: + - `Jest` + [jest-monocart-coverage](https://github.com/cenfun/jest-monocart-coverage) + - `Vitest` + [vitest-monocart-coverage](https://github.com/cenfun/vitest-monocart-coverage) +```js +const coverageOptions = { + name: 'My Unit Test Coverage Report', + outputDir: "./coverage-reports/unit", + reports: [ + ['raw', { + // relative path will be "./coverage-reports/unit/raw" + // defaults to raw + outputDir: "raw" + }], + ['v8'], + ['console-details'] + ] +}; +``` + +- We also have `raw` coverage data from `e2e test`, which is output to `./coverage-reports/e2e/raw`. E2E test examples: + - `Playwright` + [monocart-reporter](https://github.com/cenfun/monocart-reporter) with coverage API + - `Playwright` + `MCR`, see [playwright-coverage](https://github.com/cenfun/playwright-coverage) + - see more [Integration Examples](#integration-examples) + +- Then create a script `merge-coverage.js` to generate a merged report with option `inputDir`. +```js +// merge-coverage.js +const fs = require('fs'); +const { CoverageReport } = require('monocart-coverage-reports'); +const inputDir = [ + './coverage-reports/unit/raw', + './coverage-reports/e2e/raw' +]; +const coverageOptions = { + name: 'My Merged Coverage Report', + inputDir, + outputDir: './coverage-reports/merged', + + // filter for both unit and e2e + entryFilter: { + '**/node_modules/**': false, + '**/*': true + }, + sourceFilter: { + '**/node_modules/**': false, + '**/src/**': true + }, + + sourcePath: (filePath, info) => { + // Unify the file path for the same files + // For example, the file index.js has different paths: + // unit: unit-dist/src/index.js + // e2e: e2e-dist/src/index.js + // return filePath.replace("unit-dist/", "").replace("e2e-dist/", "") + return filePath; + }, + + reports: [ + ['v8'], + ['console-details'] + ], + + onEnd: () => { + // remove the raw files if it useless + // inputDir.forEach((p) => { + // fs.rmSync(p, { + // recursive: true, + // force: true + // }); + // }); + } +}; +await new CoverageReport(coverageOptions).generate(); +``` +- Running script `node path/to/merge-coverage.js` after all the tests are completed. All the command scripts are probably like following: +```json +{ + "scripts": { + "test:unit": "jest", + "test:e2e": "playwright test", + "merge-coverage": "node path/to/merge-coverage.js", + "test": "npm run test:unit && npm run test:e2e && npm run merge-coverage" + } +} +``` +see example: [merge-code-coverage](https://github.com/cenfun/merge-code-coverage) + +## Common issues +### Unexpected coverage +In most cases, it happens when the coverage of the generated code is converted to the coverage of the original code through a sourcemap. In other words, it's an issue with the sourcemap. Most of the time, we can solve this by setting `minify` to `false` in the configuration of build tools. Let's take a look at an example: +```js +const a = tf ? 'true' : 'false'; + ^ ^ ^ + m1 p m2 +``` +In the generated code, there is a position `p`, and we need to find out its corresponding position in the original code. Unfortunately, there is no matched mapping for the position `p`. Instead, it has two adjacent upstream and downstream mappings `m1` and `m2`, so, the original position of `p` that we are looking for, might not be able to be precisely located. Especially, the generated code is different from the original code, such as the code was minified, compressed or converted, it is difficult to find the exact original position without matched mapping. +- Further understanding of sourcemap, try [Debug for Coverage and Sourcemap](#debug-for-coverage-and-sourcemap) + +How `MCR` Works: +- 1, Trying to fix the original position with string comparison and [`diff-sequences`](https://github.com/jestjs/jest/tree/main/packages/diff-sequences). However, for non-JS code, such as Vue template, JSX, etc., it might be hard to find a perfect solution. +- 2, Finding all functions, statements and branches by parsing the source code [AST](https://github.com/acornjs/acorn). (There is a small issue is the V8 cannot provide effective branch coverage information for `AssignmentPattern`) + + +### Unparsable source +It happens during the parsing of the source code into AST, if the source code is not in the standard ECMAScript. For example `ts`, `jsx` and so on. There is a option to fix it, which is to manually compile the source code for these files. +```js +import * as fs from "fs"; +import * as path from "path"; +import { fileURLToPath } from "url"; +import * as TsNode from 'ts-node'; +const coverageOptions = { + onEntry: async (entry) => { + const filePath = fileURLToPath(entry.url) + const originalSource = fs.readFileSync(filePath).toString("utf-8"); + const fileName = path.basename(filePath); + const tn = TsNode.create({}); + const source = tn.compile(originalSource, fileName); + entry.fake = false; + entry.source = source; + } +} +``` + +### JavaScript heap out of memory +When there are a lot of raw v8 coverage files to process, it may cause OOM. We can try the following Node.js options: +```sh +- run: npm run test:coverage + env: + NODE_OPTIONS: --max-old-space-size=8192 +``` + + +## Debug for Coverage and Sourcemap +> Sometimes, the coverage is not what we expect. The next step is to figure out why, and we can easily find out the answer step by step through debugging. +- Start debugging for v8 report with option `logging: 'debug'` +```js +const coverageOptions = { + logging: 'debug', + reports: [ + ['v8'], + ['console-details'] + ] +}; +``` +When `logging` is `debug`, the raw report data will be preserved in `[outputDir]/.cache` or `[outputDir]/raw` if `raw` report is used. And the dist file will be preserved in the V8 list, and by opening the browser's devtool, it makes data verification visualization effortless. +![](./assets/debug-coverage.png) + +- Check sourcemap with [Source Map Visualization](https://evanw.github.io/source-map-visualization/) + +![](./assets/debug-sourcemap.png) + +- Generate additional source and sourcemap files to cache or raw dir +```js +const coverageOptions = { + logging: 'debug', + sourceMap: true +}; +``` + +- Show time logs with env `MCR_LOG_TIME` +```js +process.env.MCR_LOG_TIME = true +``` + +## Integration with Any Testing Framework +- API + - Collecting coverage data when any stage of the test is completed, and adding the coverage data to the coverage reporter. `await mcr.add(coverageData)` + - Generating the coverage reports after the completion of all tests. `await mcr.generate()` + - see [Multiprocessing Support](#multiprocessing-support) +- CLI + - Wrapping with any CLI. `mcr your-cli --your-arguments` + - see [Command line](#command-line) + +## Integration Examples + +### [Playwright](https://github.com/microsoft/playwright) +- [playwright-coverage](https://github.com/cenfun/playwright-coverage) - Example for Playwright coverage reports +- [playwright-bdd-coverage](https://github.com/cenfun/playwright-bdd-coverage) - Example for Playwright BDD coverage reports +- [monocart-reporter](https://github.com/cenfun/monocart-reporter) - Playwright custom reporter, supports generating [Code coverage report](https://github.com/cenfun/monocart-reporter?#code-coverage-report) +- Coverage for component testing with `monocart-reporter`: + - [playwright-ct-vue](https://github.com/cenfun/playwright-ct-vue) + - [playwright-ct-react](https://github.com/cenfun/playwright-ct-react) + - [playwright-ct-svelte](https://github.com/cenfun/playwright-ct-svelte) +- Coverage for Next.js, both server side and client side: + - [nextjs-with-playwright](https://github.com/cenfun/nextjs-with-playwright) + - [nextjs-with-playwright-istanbul](https://github.com/cenfun/nextjs-with-playwright-istanbul) +- Coverage for Remix: + - [remix-with-playwright](https://github.com/cenfun/remix-with-playwright) +- see [Collecting V8 Coverage Data with Playwright](#collecting-v8-coverage-data-with-playwright) + +### [c8](https://github.com/bcoe/c8) +- c8 has integrated `MCR` as an experimental feature since [v10.1.0](https://github.com/bcoe/c8/releases/tag/v10.1.0) +```sh +c8 --experimental-monocart --reporter=v8 --reporter=console-details node foo.js +``` + +### [CodeceptJS](https://github.com/codeceptjs/CodeceptJS) +- CodeceptJS is a [BDD](https://codecept.io/bdd/) + [AI](https://codecept.io/ai/) testing framework for e2e testing, it has integrated `MCR` since [v3.5.15](https://github.com/codeceptjs/CodeceptJS/releases/tag/3.5.15), see [plugins/coverage](https://codecept.io/plugins/#coverage) + +### [VSCode](https://github.com/microsoft/vscode) +- [Monocart Coverage for VSCode](https://github.com/cenfun/monocart-coverage-vscode) - Shows native V8 code coverage in VSCode + +### [Jest](https://github.com/jestjs/jest/) +- [jest-monocart-coverage](https://github.com/cenfun/jest-monocart-coverage) - Jest custom reporter for coverage reports +- [merge-code-coverage](https://github.com/cenfun/merge-code-coverage) - Example for merging code coverage (Jest unit + Playwright e2e sharding) + +### [Vitest](https://github.com/vitest-dev/vitest) +- [vitest-monocart-coverage](https://github.com/cenfun/vitest-monocart-coverage) - Vitest custom provider module for coverage reports +- [merge-code-coverage-vitest](https://github.com/cenfun/merge-code-coverage-vitest) - Example for merging code coverage (Vitest unit + Playwright e2e sharding) + +### [Node Test Runner](https://nodejs.org/docs/latest/api/test.html) +- [node-monocart-coverage](https://github.com/cenfun/node-monocart-coverage) - Custom reporter for Node test runner for coverage + +### [Puppeteer](https://github.com/puppeteer/puppeteer/) +- [jest-puppeteer-coverage](https://github.com/cenfun/jest-puppeteer-coverage) - Example for Jest puppeteer coverage +- [maplibre-gl-js](https://github.com/maplibre/maplibre-gl-js) - Example for Jest (unit) + Puppeteer (e2e) + Codecov +- see [Collecting Raw V8 Coverage Data with Puppeteer](#collecting-raw-v8-coverage-data-with-puppeteer) + +### [Cypress](https://github.com/cypress-io/cypress) +- [cypress-monocart-coverage](https://github.com/cenfun/cypress-monocart-coverage) - Cypress plugin for coverage reports + +### [WebdriverIO](https://github.com/webdriverio/webdriverio) +- [wdio-monocart-service](https://github.com/cenfun/wdio-monocart-service) - WebdriverIO service for coverage reports + +### [Storybook Test Runner](https://github.com/storybookjs/test-runner) +- [storybook-monocart-coverage](https://github.com/cenfun/storybook-monocart-coverage) - Example for Storybook V8 coverage reports + +### [TestCafe](https://github.com/DevExpress/testcafe) +- [testcafe-reporter-coverage](https://github.com/cenfun/testcafe-reporter-coverage) - TestCafe custom reporter for coverage reports + +### [Selenium Webdriver](https://github.com/seleniumhq/selenium) +- [selenium-webdriver-coverage](https://github.com/cenfun/selenium-webdriver-coverage) - Example for Selenium Webdriver V8 coverage reports + +### [Mocha](https://github.com/mochajs/mocha) +```sh +mcr mocha ./test/**/*.js +``` + +### [TypeScript](https://github.com/microsoft/typescript) + +- [tsx](https://github.com/privatenumber/tsx) +```sh +cross-env NODE_OPTIONS="--import tsx" npx mcr tsx ./src/example.ts +cross-env NODE_OPTIONS="--import tsx" npx mcr mocha ./test/**/*.ts +# Node.js v18.19.0 + +mcr --import tsx tsx ./src/example.ts +mcr --import tsx mocha ./test/**/*.ts +``` +- [ts-node](https://github.com/TypeStrong/ts-node) +```sh +cross-env NODE_OPTIONS="--loader ts-node/esm --no-warnings" npx mcr ts-node ./src/example.ts +cross-env NODE_OPTIONS="--loader ts-node/esm --no-warnings" npx mcr mocha ./test/**/*.ts +``` + +### [AVA](https://github.com/avajs/ava) +```sh +mcr ava +``` + +### [Codecov](https://codecov.com/) +[![codecov](https://codecov.io/gh/cenfun/monocart-coverage-reports/graph/badge.svg?token=H0LW7UKYU3)](https://codecov.io/gh/cenfun/monocart-coverage-reports) +- Supports native `codecov` built-in report ([specification](https://docs.codecov.com/docs/codecov-custom-coverage-format)) +```js +const coverageOptions = { + outputDir: "./coverage-reports", + reports: [ + ['codecov'] + ] +}; +``` +- Github actions: +```yml +- name: Codecov + uses: codecov/codecov-action@v4 + with: + token: ${{ secrets.CODECOV_TOKEN }} + files: ./coverage-reports/codecov.json +``` + +### [Codacy](https://www.codacy.com/) +[![Codacy](https://app.codacy.com/project/badge/Coverage/715016ea8e90479db875b777db8bad55)](https://app.codacy.com/gh/cenfun/monocart-coverage-reports/dashboard?utm_source=gh&utm_medium=referral&utm_content=&utm_campaign=Badge_coverage) +- Using `lcov` report: +```js +const coverageOptions = { + outputDir: "./coverage-reports", + lcov: true +}; +``` +- Github actions: +```yml +- name: Codacy Coverage Reporter + uses: codacy/codacy-coverage-reporter-action@v1 + with: + project-token: ${{ secrets.CODACY_PROJECT_TOKEN }} + coverage-reports: ./docs/mcr/lcov.info +``` + +### [Coveralls](https://coveralls.io/) +[![Coverage Status](https://coveralls.io/repos/github/cenfun/monocart-coverage-reports/badge.svg?branch=main)](https://coveralls.io/github/cenfun/monocart-coverage-reports?branch=main) +- Using `lcov` report: +```js +const coverageOptions = { + outputDir: "./coverage-reports", + lcov: true +}; +``` +- Github actions: +```yml +- name: Coveralls + uses: coverallsapp/github-action@v2 + with: + files: ./coverage-reports/lcov.info +``` + +### [Sonar Cloud](https://sonarcloud.io/) +[![Coverage](https://sonarcloud.io/api/project_badges/measure?project=monocart-coverage-reports&metric=coverage)](https://sonarcloud.io/summary/new_code?id=monocart-coverage-reports) +- Using `lcov` report. Github actions example: +```yml +- name: Analyze with SonarCloud + uses: sonarsource/sonarcloud-github-action@master + env: + SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} + with: + projectBaseDir: ./ + args: > + -Dsonar.organization=cenfun + -Dsonar.projectKey=monocart-coverage-reports + -Dsonar.projectName=monocart-coverage-reports + -Dsonar.javascript.lcov.reportPaths=docs/mcr/lcov.info + -Dsonar.sources=lib + -Dsonar.tests=test + -Dsonar.exclusions=dist/*,packages/* +``` + +## Contributing +- Node.js 20+ +- VSCode (extensions: eslint/stylelint/vue) +```sh +npm install +npx playwright install --with-deps + +npm run build +npm run test + +npm run dev +``` +- Refreshing `eol=lf` for snapshot of test (Windows) +```sh +git add . -u +git commit -m "Saving files before refreshing line endings" + +npm run eol +``` + +## Thanks +- [@bcoe](https://github.com/bcoe) +- [@edumserrano](https://github.com/edumserrano) \ No newline at end of file diff --git a/node_modules/monocart-coverage-reports/README.zh-Hans.md b/node_modules/monocart-coverage-reports/README.zh-Hans.md new file mode 100644 index 0000000..3d33448 --- /dev/null +++ b/node_modules/monocart-coverage-reports/README.zh-Hans.md @@ -0,0 +1,1191 @@ +# Monocart Coverage Reports + +[![npm](https://img.shields.io/npm/v/monocart-coverage-reports)](https://www.npmjs.com/package/monocart-coverage-reports) +![license](https://img.shields.io/github/license/cenfun/monocart-coverage-reports) +![build](https://img.shields.io/github/actions/workflow/status/cenfun/monocart-coverage-reports/ci.yml) +[![install size](https://packagephobia.com/badge?p=monocart-coverage-reports)](https://packagephobia.com/result?p=monocart-coverage-reports) +[![npm graph](https://img.shields.io/badge/npm-graph-blue)](https://npmgraph.js.org/?q=monocart-coverage-reports) +![dependencies](https://img.shields.io/librariesio/github/cenfun/monocart-coverage-reports) +[![downloads](https://devimg.vercel.app/npm/downloads/monocart-coverage-reports?label={total}%20downloads/month)](https://www.npmjs.com/package/monocart-coverage-reports) + +🌐 [English](README.md) | 简体中文 + +> JS代码覆盖率工具,用来生成原生的[V8](https://v8.dev/blog/javascript-code-coverage)或者[Istanbul](https://istanbul.js.org/)代码覆盖率报告 + +* [用法](#usage) +* [选项配置](#options) +* [所有支持的报告类型](#available-reports) +* [比较两种报告](#compare-reports) +* [如何收集Istanbul覆盖率数据](#collecting-istanbul-coverage-data) +* [如何收集V8覆盖率数据](#collecting-v8-coverage-data) + - [用Playwright](#collecting-v8-coverage-data-with-playwright) + - [用Puppeteer](#collecting-raw-v8-coverage-data-with-puppeteer) + - [从Node.js](#collecting-v8-coverage-data-from-nodejs) + - [使用`CDPClient`API](#collecting-v8-coverage-data-with-cdpclient-api) + - [参考V8覆盖率的API](#v8-coverage-data-api) +* [过滤V8覆盖率数据](#filtering-results) +* [使用 `sourcePath` 修改源文件路径](#resolve-sourcepath-for-the-source-files) +* [为未测试的文件添加空的覆盖率报告](#adding-empty-coverage-for-untested-files) +* [onEnd回调函数](#onend-hook) +* [如何忽略未覆盖的代码](#ignoring-uncovered-codes) +* [多进程支持](#multiprocessing-support) +* [如何使用CLI命令行](#command-line) +* [如何加载配置文件](#config-file) +* [如何合并覆盖率报告](#merge-coverage-reports) + - [自动合并](#automatic-merging) + - [手动合并](#manual-merging) +* [常见问题](#common-issues) + - [Unexpected coverage](#unexpected-coverage) + - [Unparsable source](#unparsable-source) + - [JavaScript heap out of memory](#javascript-heap-out-of-memory) +* [如何调试覆盖率数据和查看sourcemap](#debug-for-coverage-and-sourcemap) +* [如何跟其他框架集成](#integration-with-any-testing-framework) +* [集成的例子](#integration-examples) + - [Playwright](#playwright) + - [c8](#c8) + - [CodeceptJS](#codeceptjs) + - [VSCode](#vscode) + - [Jest](#jest) + - [Vitest](#vitest) + - [Node Test Runner](#node-test-runner) + - [Puppeteer](#puppeteer) + - [Cypress](#cypress) + - [WebdriverIO](#webdriverio) + - [Storybook Test Runner](#storybook-test-runner) + - [TestCafe](#testcafe) + - [Selenium Webdriver](#selenium-webdriver) + - [Mocha](#mocha) + - [TypeScript](#typescript) + - [AVA](#ava) + - [Codecov](#codecov) + - [Codacy](#codacy) + - [Coveralls](#coveralls) + - [Sonar Cloud](#sonar-cloud) +* [Contributing](#contributing) +* [更新日志](CHANGELOG.md) +* [感谢](#thanks) + +## Usage +> 推荐使用 [Node.js 20+](https://nodejs.org/). +- 安装 +```sh +npm install monocart-coverage-reports +``` +- API +```js +const MCR = require('monocart-coverage-reports'); +const mcr = MCR({ + name: 'My Coverage Report - 2024-02-28', + outputDir: './coverage-reports', + reports: ["v8", "console-details"], + cleanCache: true +}); +await mcr.add(coverageData); +await mcr.generate(); +``` +也可以使用ESM的 `import` 然后加载[配置文件](#config-file) +```js +import { CoverageReport } from 'monocart-coverage-reports'; +const mcr = new CoverageReport(); +await mcr.loadConfig(); +``` +参见 [多进程支持](#multiprocessing-support) + +- CLI +```sh +mcr node my-app.js -r v8,console-details +``` +参见 [命令行](#command-line) + +## Options +- 默认选项: [lib/default/options.js](./lib/default/options.js) +- 选项的类型描述,见 `CoverageReportOptions` [lib/index.d.ts](./lib/index.d.ts) +- [配置文件](#config-file) + +## Available Reports + +> 内置V8报告(仅V8格式数据支持): + +- `v8` + - 推荐使用: + - 全新的原生V8覆盖率报告界面,更好的用户体验 + - 支持原生的Bytes覆盖率指标 + - 支持高性能处理大数据 + - 支持任何运行时代码的覆盖率(压缩后的) + - 支持CSS代码覆盖率(用于分析CSS的冗余代码) + - 对Sourcemap转换有更好的支持 + - 预览: [V8](https://cenfun.github.io/monocart-coverage-reports/v8) and [more](https://cenfun.github.io/monocart-coverage-reports/) + +![](./assets/v8.gif) + +- `v8-json` + - 保存 `CoverageResults` 到一个json文件 (默认是 [`coverage-report.json`](https://cenfun.github.io/monocart-coverage-reports/v8-and-istanbul/coverage-report.json)) + - 用于VSCode扩展来显示原生V8代码覆盖率: [Monocart Coverage for VSCode](https://github.com/cenfun/monocart-coverage-vscode) + +![](./assets/mcv.gif) + +> 内置Istanbul报告 (V8和Istanbul格式数据都支持): + +- `clover` +- `cobertura` +- `html` + - [Istanbul html](https://cenfun.github.io/monocart-coverage-reports/istanbul/) + - [V8 to Istanbul](https://cenfun.github.io/monocart-coverage-reports/v8-and-istanbul/istanbul) +- `html-spa` +- `json` +- `json-summary` +- `lcov` +- `lcovonly` + - [V8 lcov.info](https://cenfun.github.io/monocart-coverage-reports/v8/lcov.info) + - [Istanbul lcov.info](https://cenfun.github.io/monocart-coverage-reports/istanbul/lcov.info) +- `none` +- `teamcity` +- `text` +- `text-lcov` +- `text-summary` + +> 其他内置报告 (V8和Istanbul格式数据都支持): + +- `codecov` 保存覆盖率数据到 [Codecov](https://docs.codecov.com/docs/codecov-custom-coverage-format) 专属的json文件 (默认是`codecov.json`), 见[例子](https://app.codecov.io/github/cenfun/monocart-coverage-reports) + +- `codacy` 保存覆盖率数据到 [Codacy](https://api.codacy.com/swagger#tocscoveragereport) 专属的json文件 (默认是`codacy.json`) + +- `console-summary` 在控制台显示覆盖率概要 + +![](./assets/console-summary.png) + +- `console-details` 在控制台显示每个文件的覆盖率概要。如果是Github actions,可以使用环境变量`FORCE_COLOR: true`来强制开启颜色支持 + +![](./assets/console-details.png) + +- `markdown-summary` 保存概要信息到markdown文件 (默认是`coverage-summary.md`)。 如果是Github actions, 可以把markdown的内容添加到[a job summary](https://docs.github.com/en/actions/using-workflows/workflow-commands-for-github-actions#adding-a-job-summary) +```sh +cat path-to/coverage-summary.md >> $GITHUB_STEP_SUMMARY +``` +![](./assets/markdown-summary.png) + +- `markdown-details` 保存覆盖率详情到markdown文件 (默认是 `coverage-details.md`) + - 预览运行结果 [runs](https://github.com/cenfun/monocart-coverage-reports/actions/workflows/ci.yml) + +- `raw` 只是保存原始覆盖率数据, 用于使用`inputDir`参数来导入多个原始数据进行合并报告。参见 [合并覆盖率报告](#merge-coverage-reports) + +- 自定义报告 + ```js + { + reports: [ + [path.resolve('./test/custom-istanbul-reporter.js'), { + type: 'istanbul', + file: 'custom-istanbul-coverage.text' + }], + [path.resolve('./test/custom-v8-reporter.js'), { + type: 'v8', + outputFile: 'custom-v8-coverage.json' + }], + [path.resolve('./test/custom-v8-reporter.mjs'), { + type: 'both' + }] + ] + } + ``` + - Istanbul自定义报告 + > 例子: [./test/custom-istanbul-reporter.js](./test/custom-istanbul-reporter.js), see [istanbul built-in reporters' implementation](https://github.com/istanbuljs/istanbuljs/tree/master/packages/istanbul-reports/lib) for reference. + - V8自定义报告 + > 例子: [./test/custom-v8-reporter.js](./test/custom-v8-reporter.js) + +### Multiple Reports: +如何配置多个报告 +```js +const MCR = require('monocart-coverage-reports'); +const coverageOptions = { + outputDir: './coverage-reports', + reports: [ + // build-in reports + ['console-summary'], + ['v8'], + ['html', { + subdir: 'istanbul' + }], + ['json', { + file: 'my-json-file.json' + }], + 'lcovonly', + + // custom reports + // Specify reporter name with the NPM package + ["custom-reporter-1"], + ["custom-reporter-2", { + type: "istanbul", + key: "value" + }], + // Specify reporter name with local path + ['/absolute/path/to/custom-reporter.js'] + ] +} +const mcr = MCR(coverageOptions); +``` + +## Compare Reports +> 如果是V8数据格式使用Istanbul的报告,将自动从V8转换到Istanbul + +| | Istanbul | V8 | V8 to Istanbul | +| :--------------| :------ | :------ | :---------------------- | +| 数据格式 | [Istanbul](https://github.com/gotwarlost/istanbul/blob/master/coverage.json.md) (Object) | [V8](#v8-coverage-data-format) (Array) | [V8](#v8-coverage-data-format) (Array) | +| 输出报告 | [Istanbul reports](#available-reports) | [V8 reports](#available-reports) | [Istanbul reports](#available-reports) | +| - Bytes 字节覆盖率 | ❌ | ✅ | ❌ | +| - Statements 语句覆盖率 | ✅ | ✅ | ✅ | +| - Branches 分支覆盖率 | ✅ | ✅ | ✅ | +| - Functions 函数覆盖率 | ✅ | ✅ | ✅ | +| - Lines 行覆盖率 | ✅ | ✅ | ✅ | +| - Execution counts 函数执行数 | ✅ | ✅ | ✅ | +| CSS 覆盖率 | ❌ | ✅ | ✅ | +| 压缩过的代码 | ❌ | ✅ | ❌ | + +## Collecting Istanbul Coverage Data +- 在收集Istanbul覆盖率数据之前,需要编译源代码来安装Istanbul计数器 + - webpack babel-loader: [babel-plugin-istanbul](https://github.com/istanbuljs/babel-plugin-istanbul), 参见例子: [webpack.config-istanbul.js](./test/build/webpack.config-istanbul.js) + - 官方CLI: [nyc instrument](https://github.com/istanbuljs/nyc/blob/master/docs/instrument.md) 或API: [istanbul-lib-instrument](https://github.com/istanbuljs/istanbuljs/blob/main/packages/istanbul-lib-instrument/api.md) + - vite: [vite-plugin-istanbul](https://github.com/ifaxity/vite-plugin-istanbul) + - rollup: [rollup-plugin-istanbul](https://github.com/artberri/rollup-plugin-istanbul) + - swc: [swc-plugin-coverage-instrument](https://github.com/kwonoj/swc-plugin-coverage-instrument) + +- 从浏览器 + - Istanbul的覆盖率数据会保存到全局的`window.__coverage__`,直接读取即可, 参见例子: [test-istanbul.js](./test/test-istanbul.js) + +- 从Node.js + - 同理对于Node.js会保存到全局的`global.__coverage__` + +- 使用CDP + - `getIstanbulCoverage()` 参见[`CDPClient` API](#collecting-v8-coverage-data-with-cdpclient-api) + +## Collecting V8 Coverage Data +- 在收集V8覆盖率数据之前,需要开启构建工具的`sourcemap`支持,并且不要压缩代码 + - [webpack](https://webpack.js.org/configuration/): `devtool: source-map` and `mode: development`, example [webpack.config-v8.js](./test/build/webpack.config-v8.js) + - [rollup](https://rollupjs.org/configuration-options/): `sourcemap: true` and `treeshake: false` + - [esbuild](https://esbuild.github.io/api/): `sourcemap: true`, `treeShaking: false` and `minify: false` + - [vite](https://vitejs.dev/config/build-options.html): `sourcemap: true` and `minify: false` + +- 浏览器 (仅支持基于Chromium的浏览器) + - [使用Playwright](#collecting-v8-coverage-data-with-playwright) + - [使用Puppeteer](#collecting-raw-v8-coverage-data-with-puppeteer) + +- 从Node.js + - [从Node.js收集V8覆盖率数据](#collecting-v8-coverage-data-from-nodejs) + +- 使用CDP + - [使用`CDPClient` API收集V8覆盖率数据](#collecting-v8-coverage-data-with-cdpclient-api) + +### Collecting V8 Coverage Data with Playwright +使用Playwright的覆盖接口收集覆盖率数据 +```js +await Promise.all([ + page.coverage.startJSCoverage({ + // reportAnonymousScripts: true, + resetOnNavigation: false + }), + page.coverage.startCSSCoverage({ + // Note, anonymous styles (without sourceURLs) are not supported, alternatively, you can use CDPClient + resetOnNavigation: false + }) +]); + +await page.goto("your page url"); + +const [jsCoverage, cssCoverage] = await Promise.all([ + page.coverage.stopJSCoverage(), + page.coverage.stopCSSCoverage() +]); + +const coverageData = [... jsCoverage, ... cssCoverage]; + +``` +使用 `@playwright/test` 的 [`Automatic fixtures`](https://playwright.dev/docs/test-fixtures#automatic-fixtures)收集覆盖率数据, 见例子: [fixtures.ts](https://github.com/cenfun/playwright-coverage/blob/main/fixtures.ts) +参见例子 [./test/test-v8.js](./test/test-v8.js), [css](./test/test-css.js) + + +### Collecting Raw V8 Coverage Data with Puppeteer +使用Puppeteer的覆盖接口收集覆盖率数据,注意Puppeteer默认不会提供原生V8的覆盖率数据,需要设置`includeRawScriptCoverage` +```js +await Promise.all([ + page.coverage.startJSCoverage({ + // reportAnonymousScripts: true, + resetOnNavigation: false, + // provide raw v8 coverage data + includeRawScriptCoverage: true + }), + page.coverage.startCSSCoverage({ + resetOnNavigation: false + }) +]); + +await page.goto("your page url"); + +const [jsCoverage, cssCoverage] = await Promise.all([ + page.coverage.stopJSCoverage(), + page.coverage.stopCSSCoverage() +]); + +// to raw V8 script coverage +const coverageData = [... jsCoverage.map((it) => { + return { + source: it.text, + ... it.rawScriptCoverage + }; +}), ... cssCoverage]; +``` +参见: [./test/test-puppeteer.js](./test/test-puppeteer.js) + +### Collecting V8 Coverage Data from Node.js +有多种方法可以从Node.js收集V8覆盖率数据: +- [NODE_V8_COVERAGE](https://nodejs.org/docs/latest/api/cli.html#node_v8_coveragedir)=`dir` + - 使用Node.js环境变量`NODE_V8_COVERAGE`=`dir`来启动程序, 然后在进程正常结束之后,覆盖率数据将自动保存到指定的`dir`目录. + - 从`dir`目录读取所有的JSON文件,来生成覆盖率报告 + - 参见例子: + > cross-env NODE_V8_COVERAGE=`.temp/v8-coverage-env` node [./test/test-node-env.js](./test/test-node-env.js) && node [./test/generate-report.js](./test/generate-report.js) + +- [V8](https://nodejs.org/docs/latest/api/v8.html#v8takecoverage) API + NODE_V8_COVERAGE + - 如果进程不能正常结束,比如被强制关闭,或者压根就不结束,比如启动了一个服务类的,那么需要手动写入覆盖率数据,这里需要调用接口`v8.takeCoverage()` + - 参见例子: + > cross-env NODE_V8_COVERAGE=`.temp/v8-coverage-api` node [./test/test-node-api.js](./test/test-node-api.js) + +- [Inspector](https://nodejs.org/docs/latest/api/inspector.html) API + - 首先连接到Node.js的V8 inspector + - 然后使用inspector的覆盖相关API来开启和收集覆盖率数据 + - 参见例子: + > node [./test/test-node-ins.js](./test/test-node-ins.js) + - vm的例子 (注意这里需要使用`scriptOffset`,因为vm里一般都会加一层包裹代码,需要这个偏移位置来修正覆盖率数据块的位置): + > node [./test/test-node-vm.js](./test/test-node-vm.js) + +- [CDP](https://chromedevtools.github.io/devtools-protocol/) API + - 开启[Node调试](https://nodejs.org/en/guides/debugging-getting-started/) + - 使用CDP的覆盖率接口开启和收集覆盖率数据 + - 参见例子: + > node --inspect=9229 [./test/test-node-cdp.js](./test/test-node-cdp.js) + +- [Node Debugging](https://nodejs.org/en/guides/debugging-getting-started) + CDP + NODE_V8_COVERAGE + V8 API + - 如果启动了一个Node服务,可以手动调用`v8.takeCoverage()`接口来保存覆盖率数据,开启Node调试就可以远程通过CDP连接的`Runtime.evaluate`,来调用这个接口. + - 参见[koa](https://github.com/koajs/koa)的例子: + > node [./test/test-node-koa.js](./test/test-node-koa.js) + +- [Child Process](https://nodejs.org/docs/latest/api/child_process.html) + NODE_V8_COVERAGE + - 如果是子进程,可参见 [命令行](#command-line) + +### Collecting V8 Coverage Data with `CDPClient` API +- `CDPClient`为`MCR`提供的内置接口类,用来更便捷的处理覆盖率相关数据,所有的API如下 +```js +// 开始和停止并收集JS的覆盖率数据 +startJSCoverage: () => Promise; +stopJSCoverage: () => Promise; + +// 开始和停止并收集CSS的覆盖率数据,支持匿名文件(比如style里的css) +startCSSCoverage: () => Promise; +stopCSSCoverage: () => Promise; + +// 开始和停止并收集JS和CSS的覆盖率数据 +startCoverage: () => Promise; +stopCoverage: () => Promise; + +/** 如果开启了NODE_V8_COVERAGE,这个接口用来手动保存当前覆盖率数据 */ +writeCoverage: () => Promise; + +/** 收集istanbul覆盖率数据 */ +getIstanbulCoverage: (coverageKey?: string) => Promise; +``` + +- 结合使用Node调试端口`--inspect=9229` 或者浏览器调试端口 `--remote-debugging-port=9229` +```js +const MCR = require('monocart-coverage-reports'); +const client = await MCR.CDPClient({ + port: 9229 +}); +await client.startJSCoverage(); +// run your test here +const coverageData = await client.stopJSCoverage(); +``` + +- 结合使用 [Playwright CDPSession](https://playwright.dev/docs/api/class-cdpsession) +```js +const { chromium } = require('playwright'); +const MCR = require('monocart-coverage-reports'); +const browser = await chromium.launch(); +const page = await browser.newPage(); +const session = await page.context().newCDPSession(page); +const client = await MCR.CDPClient({ + session +}); +// both js and css coverage +await client.startCoverage(); +// run your test page here +await page.goto("your page url"); +const coverageData = await client.stopCoverage(); +``` + +- 结合使用 [Puppeteer CDPSession](https://pptr.dev/api/puppeteer.cdpsession) +```js +const puppeteer = require('puppeteer'); +const MCR = require('monocart-coverage-reports'); +const browser = await puppeteer.launch({}); +const page = await browser.newPage(); +const session = await page.target().createCDPSession(); +const client = await MCR.CDPClient({ + session +}); +// both js and css coverage +await client.startCoverage(); +// run your test page here +await page.goto("your page url"); +const coverageData = await client.stopCoverage(); +``` + +- 结合使用 [Selenium Webdriver](https://www.selenium.dev/documentation/webdriver/) WebSocket (仅支持Chrome/Edge浏览器) +```js +const { Builder, Browser } = require('selenium-webdriver'); +const MCR = require('monocart-coverage-reports'); +const driver = await new Builder().forBrowser(Browser.CHROME).build(); +const pageCdpConnection = await driver.createCDPConnection('page'); +const session = new MCR.WSSession(pageCdpConnection._wsConnection); +const client = await MCR.CDPClient({ + session +}) +``` + +### V8 Coverage Data API +- [JavaScript V8代码覆盖官方说明](https://v8.dev/blog/javascript-code-coverage) +- [Playwright的覆盖率接口](https://playwright.dev/docs/api/class-coverage) +- [Puppeteer的覆盖率接口](https://pptr.dev/api/puppeteer.coverage) +- [DevTools Protocol的覆盖率接口](https://chromedevtools.github.io/devtools-protocol/tot/Profiler/#method-startPreciseCoverage) 参见 [ScriptCoverage](https://chromedevtools.github.io/devtools-protocol/tot/Profiler/#type-ScriptCoverage) 和 [v8-coverage](https://github.com/bcoe/v8-coverage) +```js +// Coverage data for a source range. +export interface CoverageRange { + // JavaScript script source offset for the range start. + startOffset: integer; + // JavaScript script source offset for the range end. + endOffset: integer; + // Collected execution count of the source range. + count: integer; +} +// Coverage data for a JavaScript function. +/** + * @functionName can be an empty string. + * @ranges is always non-empty. The first range is called the "root range". + * @isBlockCoverage indicates if the function has block coverage information. + If this is false, it usually means that the functions was never called. + It seems to be equivalent to ranges.length === 1 && ranges[0].count === 0. +*/ +export interface FunctionCoverage { + // JavaScript function name. + functionName: string; + // Source ranges inside the function with coverage data. + ranges: CoverageRange[]; + // Whether coverage data for this function has block granularity. + isBlockCoverage: boolean; +} +// Coverage data for a JavaScript script. +export interface ScriptCoverage { + // JavaScript script id. + scriptId: Runtime.ScriptId; + // JavaScript script name or url. + url: string; + // Functions contained in the script that has coverage data. + functions: FunctionCoverage[]; +} +export type V8CoverageData = ScriptCoverage[]; +``` + +| JavaScript Runtime | V8 Coverage | | +| :--------------| :----: | :---------------------- | +| Chrome (65%) | ✅ | Chromium-based | +| Safari (18%) | ❌ | | +| Edge (5%) | ✅ | Chromium-based | +| Firefox (2%) | ❌ | | +| Node.js | ✅ | | +| Deno | ❌ | [issue](https://github.com/denoland/deno/issues/23359) | +| Bun | ❌ | | + +## Filtering Results +## Using `entryFilter` and `sourceFilter` to filter the results for V8 report +当收集到V8的覆盖数据时,它实际上包含了所有的入口文件的覆盖率数据, 比如有以下3个文件: + +- *dist/main.js* +- *dist/vendor.js* +- *dist/something-else.js* + +这个时候可以使用`entryFilter`来过滤这些入口文件. 比如我们不需要看到`vendor.js`和`something-else.js`的覆盖率,就可以过滤掉,只剩下1个文件 + +- *dist/main.js* + +如果一个入口文件存在行内或者链接的sourcemap文件,那么我们会尝试读取并解析sourcemap,以获取入口文件包含的所有源文件,并添加到列表。此时如果`logging`没有设置成`debug`,那么这个入口文件在成功解出源文件后会被移除 + +- *src/index.js* +- *src/components/app.js* +- *node_modules/dependency/dist/dependency.js* + +这个时候可以使用`sourceFilter`来过滤这些源文件。比如我们不需要看到源文件`dependency.js`的覆盖率,就可以过滤掉,最后只剩下如下文件 + +- *src/index.js* +- *src/components/app.js* + +过滤可以使用函数: +```js +const coverageOptions = { + entryFilter: (entry) => entry.url.indexOf("main.js") !== -1, + sourceFilter: (sourcePath) => sourcePath.search(/src\//) !== -1 +}; +``` +也可以使用便捷的[`minimatch`](https://github.com/isaacs/minimatch)来匹配(推荐): +```js +const coverageOptions = { + entryFilter: "**/main.js", + sourceFilter: "**/src/**" +}; +``` +支持多个匹配: +```js +const coverageOptions = { + entryFilter: { + '**/node_modules/**': false, + '**/vendor.js': false, + '**/src/**': true + }, + sourceFilter: { + '**/node_modules/**': false, + '**/**': true + } +}; +``` +作为CLI参数(JSON字符串,Added in: v2.8): +```sh +mcr --sourceFilter "{'**/node_modules/**':false,'**/**':true}" +``` +注意,这些匹配实际上会转换成一个过滤函数(如下),所以如果一个匹配成功则会直接返回,后面的将不再继续匹配。请注意先后顺序,如果存在包含关系的,可以调整上下顺序,最后如果都未匹配,则默认返回false +```js +const coverageOptions = { + entryFilter: (entry) => { + if (minimatch(entry.url, '**/node_modules/**')) { return false; } + if (minimatch(entry.url, '**/vendor.js')) { return false; } + if (minimatch(entry.url, '**/src/**')) { return true; } + return false; // else unmatched + } +}; +``` + +### Using `filter` instead of `entryFilter` and `sourceFilter` +如果你不想定义两个过滤器,可以使用 `filter` 选项代替,可以将多个匹配合并在一起. (Added in: v2.8) +```js +const coverageOptions = { + // combined patterns + filter: { + '**/node_modules/**': false, + '**/vendor.js': false, + '**/src/**': true + '**/**': true + } +}; +``` + +## Resolve `sourcePath` for the Source Files +当一个文件从sourcemap解包,它的路径可能是个虚拟路径, 此时可以使用`sourcePath`选项来修改文件路径。比如,我们测试了多个dist包的入口文件,它们的源文件可能包含了一些共同的文件,但路径可能不同,如果我们需要相同的文件覆盖率数据可以自动合并,那么需要使用`sourcePath`来统一这些相同文件的路径 +```js +const coverageOptions = { + sourcePath: (filePath) => { + // Remove the virtual prefix + const list = ['my-dist-file1/', 'my-dist-file2/']; + for (const str of list) { + if (filePath.startsWith(str)) { + return filePath.slice(str.length); + } + } + return filePath; + } +}; +``` +它也支持简单key/value的替换: +```js +const coverageOptions = { + sourcePath: { + 'my-dist-file1/': '', + 'my-dist-file2/': '' + } +}; +``` +解决文件路径不完整的问题: +```js +const path = require("path") + +// MCR coverage options +const coverageOptions = { + sourcePath: (filePath, info)=> { + if (!filePath.includes('/') && info.distFile) { + return `${path.dirname(info.distFile)}/${filePath}`; + } + return filePath; + } +} +``` + +## Adding Empty Coverage for Untested Files +默认,未测试的文件是不会包含到覆盖率报告的,需要使用`all`选项来为这些文件添加一个空的覆盖率,也就是0% +```js +const coverageOptions = { + all: './src', + + // 支持多个目录 + all: ['./src', './lib'], +}; +``` +未测试的文件也适用于`sourceFilter`过滤器. 而且也可以指定自己的`filter`过滤器 (可以返回文件类型来支持js或css的覆盖率格式): +```js +const coverageOptions = { + all: { + dir: ['./src'], + filter: { + // exclude files + '**/ignored-*.js': false, + '**/*.html': false, + // empty css coverage + '**/*.scss': "css", + '**/*': true + } + } +}; +``` +我们可能需要编译.ts, .jsx, .vue等等这样的文件, 这样才能被默认的AST解析器解析,以得到更多的覆盖率指标的数据 +```js +const path = require("path"); +const swc = require("@swc/core"); +const coverageOptions = { + all: { + dir: ['./src'], + transformer: async (entry) => { + const { code, map } = await swc.transform(entry.source, { + filename: path.basename(entry.url), + sourceMaps: true, + isModule: true, + jsc: { + parser: { + syntax: "typescript", + jsx: true + }, + transform: {} + } + }); + entry.source = code; + entry.sourceMap = JSON.parse(map); + } + } +}; +``` + +## onEnd Hook +结束回调可以用来自定义业务需求,比如检测覆盖率是否达标,对比每个指标的thresholds,如果低于要求的值则可以抛出一个错误退出 +```js +const EC = require('eight-colors'); +const coverageOptions = { + name: 'My Coverage Report', + outputDir: './coverage-reports', + onEnd: (coverageResults) => { + const thresholds = { + bytes: 80, + lines: 60 + }; + console.log('check thresholds ...', thresholds); + const errors = []; + const { summary } = coverageResults; + Object.keys(thresholds).forEach((k) => { + const pct = summary[k].pct; + if (pct < thresholds[k]) { + errors.push(`Coverage threshold for ${k} (${pct} %) not met: ${thresholds[k]} %`); + } + }); + if (errors.length) { + const errMsg = errors.join('\n'); + console.log(EC.red(errMsg)); + // throw new Error(errMsg); + // process.exit(1); + } + } +} +``` + +## Ignoring Uncovered Codes +使用特定的注释,以`v8 ignore `开头可以忽略未覆盖的代码: +- 忽略开始到结束 +```js +/* v8 ignore start */ +function uncovered() { +} +/* v8 ignore stop */ +``` +- 忽略接下来一行或者多行 +```js +/* v8 ignore next */ +const os = platform === 'wind32' ? 'Windows' : 'Other'; + +const os = platform === 'wind32' ? 'Windows' /* v8 ignore next */ : 'Other'; + +// v8 ignore next 3 +if (platform === 'linux') { + console.log('hello linux'); +} +``` +- 兼容支持 [c8 coverage](https://github.com/bcoe/c8/?tab=readme-ov-file#ignoring-all-lines-until-told) 或 [nodejs coverage](https://nodejs.org/docs/latest/api/test.html#collecting-code-coverage) 的语法格式 +```js +/* c8 ignore start */ +function uncovered() { +} +/* c8 ignore stop */ + +/* node:coverage disable */ +function uncovered() { +} +/* node:coverage enable */ +``` + +## Multiprocessing Support +> 多进程支持可以很好的解决异步并行的情况。所有的覆盖率数据会保存到`[outputDir]/.cache`,在报告生成之后,这些缓存数据会被清除。除非开启了[调试模式](#debug-for-coverage-and-sourcemap),或者使用了`raw`报告 +- 主进程,初始化,清理之前的缓存 +```js +const MCR = require('monocart-coverage-reports'); +const coverageOptions = require('path-to/same-options.js'); +const mcr = MCR(coverageOptions); +// clean previous cache before the start of testing +// unless the running environment is new and no cache +mcr.cleanCache(); +``` + +- 子进程1, 测试业务1 +```js +const MCR = require('monocart-coverage-reports'); +const coverageOptions = require('path-to/same-options.js'); +const mcr = MCR(coverageOptions); +await mcr.add(coverageData1); +``` + +- 子进程2, 测试业务2 +```js +const MCR = require('monocart-coverage-reports'); +const coverageOptions = require('path-to/same-options.js'); +const mcr = MCR(coverageOptions); +await mcr.add(coverageData2); +``` + +- 主进程,所有测试完成之后 +```js +// generate coverage reports after the completion of testing +const MCR = require('monocart-coverage-reports'); +const coverageOptions = require('path-to/same-options.js'); +const mcr = MCR(coverageOptions); +await mcr.generate(); +``` + +## Command Line +> 使用`mcr`命令行将使用`NODE_V8_COVERAGE=dir`来启动一个[子进程](https://nodejs.org/docs/latest/api/child_process.html)运行程序,直到正常退出,然后自动从`dir`目录来读取覆盖率数据,并生成覆盖率报告 + +- 全局安装 +```sh +npm i monocart-coverage-reports -g +mcr node ./test/specs/node.test.js -r v8,console-details --lcov +``` + +- 本地项目安装 +```sh +npm i monocart-coverage-reports +npx mcr node ./test/specs/node.test.js -r v8,console-details --lcov +``` + +- 命令行参数 +直接运行 `mcr` 或 `mcr --help` 查看所有CLI的参数 + +- 使用 `--` 可以隔离子程序参数,以免两种参数混淆 +```sh +mcr -c mcr.config.js -- sub-cli -c sub-cli.config.js +``` + +- 参见例子 + - [Mocha](#mocha) + - [TypeScript](#typescript) + - [AVA](#ava) + +## Config File +根据以下优先级加载配置文件 +- 自定义配置文件(如果没有指定则加载后面的默认配置文件): + - CLI: `mcr --config ` + - API: `await mcr.loadConfig("my-config-file-path")` +- `mcr.config.js` +- `mcr.config.cjs` +- `mcr.config.mjs` +- `mcr.config.json` - json format +- `mcr.config.ts` (requires preloading the ts execution module) + +## Merge Coverage Reports +以下这些使用场景可能需要使用合并覆盖率报告: +- 多个执行环境,比如Node.js服务端,以及浏览器客户端,比如`Next.js` +- 多种测试类型,比如`Jest`单元测试,以及`Playwright`的端到端自动化测试 +- 分布式测试,测试结果保存到了多台机器或不同的容器中 + +### Automatic Merging +- 默认`MCR`在执行`generate()`时会自动合并覆盖率数据。所以可以在[多进程支持](#multiprocessing-support)下,多次添加覆盖率数据,最后将自动合并 +- 比如`Next.js`就可以同时添加前后端覆盖率数据,最后再执行`generate()`生成覆盖率报告,见例子[nextjs-with-playwright](https://github.com/cenfun/nextjs-with-playwright) +- 使用`Codecov`在线覆盖率报告服务,请设置输出`codecov`报告, 它会生成专属的`codecov.json`,如果有多个`codecov.json`文件上传,它们会自动合并数据,参见[Codecov](#codecov) 和 [合并报告说明](https://docs.codecov.com/docs/merging-reports) + +### Manual Merging +手动合并覆盖率报告需要使用`raw`报告来导出原始的覆盖率数据到指定的目录 +- 比如,单元测试保存到`./coverage-reports/unit/raw`,见例子 + - `Jest` + [jest-monocart-coverage](https://github.com/cenfun/jest-monocart-coverage) + - `Vitest` + [vitest-monocart-coverage](https://github.com/cenfun/vitest-monocart-coverage) +```js +const coverageOptions = { + name: 'My Unit Test Coverage Report', + outputDir: "./coverage-reports/unit", + reports: [ + ['raw', { + // relative path will be "./coverage-reports/unit/raw" + // defaults to raw + outputDir: "raw" + }], + ['v8'], + ['console-details'] + ] +}; +``` + +- 同样的,E2E测试保存到`./coverage-reports/e2e/raw`. 见例子: + - `Playwright` + [monocart-reporter](https://github.com/cenfun/monocart-reporter) with coverage API + - `Playwright` + `MCR`, see [playwright-coverage](https://github.com/cenfun/playwright-coverage) + - see more [Integration Examples](#integration-examples) + +- 然后创建一个`merge-coverage.js`文件,使用`inputDir`参数导入`raw`数据,来生成合并的覆盖率报告. +```js +// merge-coverage.js +const fs = require('fs'); +const { CoverageReport } = require('monocart-coverage-reports'); +const inputDir = [ + './coverage-reports/unit/raw', + './coverage-reports/e2e/raw' +]; +const coverageOptions = { + name: 'My Merged Coverage Report', + inputDir, + outputDir: './coverage-reports/merged', + + // filter for both unit and e2e + entryFilter: { + '**/node_modules/**': false, + '**/*': true + }, + sourceFilter: { + '**/node_modules/**': false, + '**/src/**': true + }, + + sourcePath: (filePath, info) => { + // Unify the file path for the same files + // For example, the file index.js has different paths: + // unit: unit-dist/src/index.js + // e2e: e2e-dist/src/index.js + // return filePath.replace("unit-dist/", "").replace("e2e-dist/", "") + return filePath; + }, + + reports: [ + ['v8'], + ['console-details'] + ], + + onEnd: () => { + // remove the raw files if it useless + // inputDir.forEach((p) => { + // fs.rmSync(p, { + // recursive: true, + // force: true + // }); + // }); + } +}; +await new CoverageReport(coverageOptions).generate(); +``` +- 最后在所有测试完成后运行`node path/to/merge-coverage.js`. 所有的执行脚本大概如下: +```json +{ + "scripts": { + "test:unit": "jest", + "test:e2e": "playwright test", + "merge-coverage": "node path/to/merge-coverage.js", + "test": "npm run test:unit && npm run test:e2e && npm run merge-coverage" + } +} +``` +参见例子: [merge-code-coverage](https://github.com/cenfun/merge-code-coverage) + +## Common issues +> 常见问题 +### Unexpected coverage +覆盖率看起来不正确,多数情况是因为sourcemap转换的问题导致的. 可以先尝试设置构建工具的 `minify=false` 也就是不要压缩代码来解决。下面来看看sourcemap存在问题的具体原因: +```js +const a = tf ? 'true' : 'false'; + ^ ^ ^ + m1 p m2 +``` +上面是经过构建工具编译过的代码,通过AST分析,位置`p`对应的原始位置是我们要找的,而从sourcemap里仅能找到离`p`最近的位置映射`m1`和`m2`,也就是位置`p`并没有精确的映射保存到sourcemap里,从而无法直接获取精确的原始位置,但我们能知道`p`的原始位置应该在`m1`和`m2`之间。 +- 参见 [调试覆盖率和sourcemap](#debug-for-coverage-and-sourcemap) + +`MCR`如何解决这个问题: +- 1, 首先会尝试使用[`diff-sequences`](https://github.com/jestjs/jest/tree/main/packages/diff-sequences)工具来比较`m1`和`m2`之间的生成代码和原始代码,找到`p`对应的字符位置,可以解决绝大多数问题。但是如果代码是非JS格式的,比如Vue模板是HTML,或JSX这些,不管怎么比较也是很难精确找到对应位置的,甚至此时的sourcemap本身都比较乱。 +- 2, 然后就是通过分析[AST](https://github.com/acornjs/acorn),找到所有的functions, statements 和 branches,因为V8覆盖率本身不提供这些指标的覆盖率. (对于分支覆盖暂不支持`AssignmentPattern`类型,因为即使分析AST也无法从V8覆盖率找到它的数据)。 + + +### Unparsable source +源码无法解析问题。由上面我们知道`MCR`通过分析源码的AST获取更多指标的覆盖率信息,但源码如果不是标准的 ECMAScript,比如`ts`, `jsx`这些,那么分析的时候就会报错,此时我们可以手动来编译这些文件(可行但不推荐). +```js +import * as fs from "fs"; +import * as path from "path"; +import { fileURLToPath } from "url"; +import * as TsNode from 'ts-node'; +const coverageOptions = { + onEntry: async (entry) => { + const filePath = fileURLToPath(entry.url) + const originalSource = fs.readFileSync(filePath).toString("utf-8"); + const fileName = path.basename(filePath); + const tn = TsNode.create({}); + const source = tn.compile(originalSource, fileName); + entry.fake = false; + entry.source = source; + } +} +``` + +### JavaScript heap out of memory +内存溢出问题可能出现在有太多的原生V8覆盖率文件要处理. 我们可以使用Node.js的一个选项来增加内存使用: +```sh +- run: npm run test:coverage + env: + NODE_OPTIONS: --max-old-space-size=8192 +``` + + +## Debug for Coverage and Sourcemap +> 当你觉得覆盖率存在问题的时候,`MCR`支持自行调试来核验覆盖率的准确性 +- 首先打开调试设置`logging: 'debug'` +```js +const coverageOptions = { + logging: 'debug', + reports: [ + ['v8'], + ['console-details'] + ] +}; +``` +调试模式下,也就是`logging`为`debug`的时候, 原始的覆盖率数据将保留在`[outputDir]/.cache`缓存目录下,不会删除,如果使用了`raw`报告,那么位置变为`[outputDir]/raw`下,这样我们可以打开v8报告的html文件,通过下面新增的一些调试帮助信息来核对覆盖率 +![](./assets/debug-coverage.png) + +- 调试sourcemap可以直接使用[Source Map Visualization](https://evanw.github.io/source-map-visualization/) (esbuild作者提供的sourcemap在线查看器) + +![](./assets/debug-sourcemap.png) + +- 生成额外的source和sourcemap文件到cache或raw文件夹 +```js +const coverageOptions = { + logging: 'debug', + sourceMap: true +}; +``` + +- 使用环境变量`MCR_LOG_TIME`显示时间日志 +```js +process.env.MCR_LOG_TIME = true +``` + +## Integration with Any Testing Framework +通用集成方案 +- 通过API接口在程序集成 + - 首先,要自行收集覆盖率数据,然后,添加到报告实例 `await mcr.add(coverageData)` + - 最后,生成覆盖率报告 `await mcr.generate()` + - 参见 [多进程支持](#multiprocessing-support) +- 通过CLI命令行与其他命令行集成 + - 直接在其他命令行前面添加mcr的命令行即可 `mcr your-cli --your-arguments` + - 参见 [命令行](#command-line) + +## Integration Examples + +### [Playwright](https://github.com/microsoft/playwright) +- [playwright-coverage](https://github.com/cenfun/playwright-coverage) - Example for Playwright coverage reports +- [playwright-bdd-coverage](https://github.com/cenfun/playwright-bdd-coverage) - Example for Playwright BDD coverage reports +- [monocart-reporter](https://github.com/cenfun/monocart-reporter) - Playwright custom reporter, supports generating [Code coverage report](https://github.com/cenfun/monocart-reporter?#code-coverage-report) +- Coverage for component testing with `monocart-reporter`: + - [playwright-ct-vue](https://github.com/cenfun/playwright-ct-vue) + - [playwright-ct-react](https://github.com/cenfun/playwright-ct-react) + - [playwright-ct-svelte](https://github.com/cenfun/playwright-ct-svelte) +- Coverage for Next.js, both server side and client side: + - [nextjs-with-playwright](https://github.com/cenfun/nextjs-with-playwright) + - [nextjs-with-playwright-istanbul](https://github.com/cenfun/nextjs-with-playwright-istanbul) +- Coverage for Remix: + - [remix-with-playwright](https://github.com/cenfun/remix-with-playwright) +- see [Collecting V8 Coverage Data with Playwright](#collecting-v8-coverage-data-with-playwright) + +### [c8](https://github.com/bcoe/c8) +- c8 has integrated `MCR` as an experimental feature since [v10.1.0](https://github.com/bcoe/c8/releases/tag/v10.1.0) +```sh +c8 --experimental-monocart --reporter=v8 --reporter=console-details node foo.js +``` + +### [CodeceptJS](https://github.com/codeceptjs/CodeceptJS) +- CodeceptJS is a [BDD](https://codecept.io/bdd/) + [AI](https://codecept.io/ai/) testing framework for e2e testing, it has integrated `MCR` since [v3.5.15](https://github.com/codeceptjs/CodeceptJS/releases/tag/3.5.15), see [plugins/coverage](https://codecept.io/plugins/#coverage) + +### [VSCode](https://github.com/microsoft/vscode) +- [Monocart Coverage for VSCode](https://github.com/cenfun/monocart-coverage-vscode) - Shows native V8 code coverage in VSCode + +### [Jest](https://github.com/jestjs/jest/) +- [jest-monocart-coverage](https://github.com/cenfun/jest-monocart-coverage) - Jest custom reporter for coverage reports +- [merge-code-coverage](https://github.com/cenfun/merge-code-coverage) - Example for merging code coverage (Jest unit + Playwright e2e sharding) + +### [Vitest](https://github.com/vitest-dev/vitest) +- [vitest-monocart-coverage](https://github.com/cenfun/vitest-monocart-coverage) - Vitest custom provider module for coverage reports +- [merge-code-coverage-vitest](https://github.com/cenfun/merge-code-coverage-vitest) - Example for merging code coverage (Vitest unit + Playwright e2e sharding) + +### [Node Test Runner](https://nodejs.org/docs/latest/api/test.html) +- [node-monocart-coverage](https://github.com/cenfun/node-monocart-coverage) - Custom reporter for Node test runner for coverage + +### [Puppeteer](https://github.com/puppeteer/puppeteer/) +- [jest-puppeteer-coverage](https://github.com/cenfun/jest-puppeteer-coverage) - Example for Jest puppeteer coverage +- [maplibre-gl-js](https://github.com/maplibre/maplibre-gl-js) - Example for Jest (unit) + Puppeteer (e2e) + Codecov +- see [Collecting Raw V8 Coverage Data with Puppeteer](#collecting-raw-v8-coverage-data-with-puppeteer) + +### [Cypress](https://github.com/cypress-io/cypress) +- [cypress-monocart-coverage](https://github.com/cenfun/cypress-monocart-coverage) - Cypress plugin for coverage reports + +### [WebdriverIO](https://github.com/webdriverio/webdriverio) +- [wdio-monocart-service](https://github.com/cenfun/wdio-monocart-service) - WebdriverIO service for coverage reports + +### [Storybook Test Runner](https://github.com/storybookjs/test-runner) +- [storybook-monocart-coverage](https://github.com/cenfun/storybook-monocart-coverage) - Example for Storybook V8 coverage reports + +### [TestCafe](https://github.com/DevExpress/testcafe) +- [testcafe-reporter-coverage](https://github.com/cenfun/testcafe-reporter-coverage) - TestCafe custom reporter for coverage reports + +### [Selenium Webdriver](https://github.com/seleniumhq/selenium) +- [selenium-webdriver-coverage](https://github.com/cenfun/selenium-webdriver-coverage) - Example for Selenium Webdriver V8 coverage reports + +### [Mocha](https://github.com/mochajs/mocha) +```sh +mcr mocha ./test/**/*.js +``` + +### [TypeScript](https://github.com/microsoft/typescript) + +- [tsx](https://github.com/privatenumber/tsx) +```sh +cross-env NODE_OPTIONS="--import tsx" npx mcr tsx ./src/example.ts +cross-env NODE_OPTIONS="--import tsx" npx mcr mocha ./test/**/*.ts +# Node.js v18.19.0 + +mcr --import tsx tsx ./src/example.ts +mcr --import tsx mocha ./test/**/*.ts +``` +- [ts-node](https://github.com/TypeStrong/ts-node) +```sh +cross-env NODE_OPTIONS="--loader ts-node/esm --no-warnings" npx mcr ts-node ./src/example.ts +cross-env NODE_OPTIONS="--loader ts-node/esm --no-warnings" npx mcr mocha ./test/**/*.ts +``` + + +### [AVA](https://github.com/avajs/ava) +```sh +mcr ava +``` + +### [Codecov](https://codecov.com/) +[![codecov](https://codecov.io/gh/cenfun/monocart-coverage-reports/graph/badge.svg?token=H0LW7UKYU3)](https://codecov.io/gh/cenfun/monocart-coverage-reports) +- Supports native `codecov` built-in report ([specification](https://docs.codecov.com/docs/codecov-custom-coverage-format)) +```js +const coverageOptions = { + outputDir: "./coverage-reports", + reports: [ + ['codecov'] + ] +}; +``` +- Github actions: +```yml +- name: Codecov + uses: codecov/codecov-action@v4 + with: + token: ${{ secrets.CODECOV_TOKEN }} + files: ./coverage-reports/codecov.json +``` + +### [Codacy](https://www.codacy.com/) +[![Codacy](https://app.codacy.com/project/badge/Coverage/715016ea8e90479db875b777db8bad55)](https://app.codacy.com/gh/cenfun/monocart-coverage-reports/dashboard?utm_source=gh&utm_medium=referral&utm_content=&utm_campaign=Badge_coverage) +- Using `lcov` report: +```js +const coverageOptions = { + outputDir: "./coverage-reports", + lcov: true +}; +``` +- Github actions: +```yml +- name: Codacy Coverage Reporter + uses: codacy/codacy-coverage-reporter-action@v1 + with: + project-token: ${{ secrets.CODACY_PROJECT_TOKEN }} + coverage-reports: ./docs/mcr/lcov.info +``` + +### [Coveralls](https://coveralls.io/) +[![Coverage Status](https://coveralls.io/repos/github/cenfun/monocart-coverage-reports/badge.svg?branch=main)](https://coveralls.io/github/cenfun/monocart-coverage-reports?branch=main) +- Using `lcov` report: +```js +const coverageOptions = { + outputDir: "./coverage-reports", + lcov: true +}; +``` +- Github actions: +```yml +- name: Coveralls + uses: coverallsapp/github-action@v2 + with: + files: ./coverage-reports/lcov.info +``` + +### [Sonar Cloud](https://sonarcloud.io/) +[![Coverage](https://sonarcloud.io/api/project_badges/measure?project=monocart-coverage-reports&metric=coverage)](https://sonarcloud.io/summary/new_code?id=monocart-coverage-reports) +- Using `lcov` report. Github actions example: +```yml +- name: Analyze with SonarCloud + uses: sonarsource/sonarcloud-github-action@master + env: + SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} + with: + projectBaseDir: ./ + args: > + -Dsonar.organization=cenfun + -Dsonar.projectKey=monocart-coverage-reports + -Dsonar.projectName=monocart-coverage-reports + -Dsonar.javascript.lcov.reportPaths=docs/mcr/lcov.info + -Dsonar.sources=lib + -Dsonar.tests=test + -Dsonar.exclusions=dist/*,packages/* +``` + +## Contributing +- Node.js 20+ +- VSCode (extensions: eslint/stylelint/vue) +```sh +npm install +npx playwright install --with-deps + +npm run build +npm run test + +npm run dev +``` +- Refreshing `eol=lf` for snapshot of test (Windows) +```sh +git add . -u +git commit -m "Saving files before refreshing line endings" + +npm run eol +``` + +## Thanks +- [@bcoe](https://github.com/bcoe) +- [@edumserrano](https://github.com/edumserrano) \ No newline at end of file diff --git a/node_modules/monocart-coverage-reports/lib/assets.js b/node_modules/monocart-coverage-reports/lib/assets.js new file mode 100644 index 0000000..218a3df --- /dev/null +++ b/node_modules/monocart-coverage-reports/lib/assets.js @@ -0,0 +1,98 @@ +const fs = require('fs'); +const path = require('path'); +const { deflateSync } = require('lz-utils'); +const Util = require('./utils/util.js'); +const assetsMap = require('./packages/monocart-coverage-assets.js'); + +const Assets = { + + getFileContent: (id) => { + const content = assetsMap[id]; + if (!content) { + Util.logError(`Not found module: ${id}`); + return ''; + } + return content; + }, + + saveHtmlReport: async (options) => { + + const { + inline, + reportData, + jsFiles, + assetsPath, + outputDir, + htmlFile, + + saveReportPath, + + reportDataFile + } = options; + + // save path + const htmlPath = path.resolve(outputDir, htmlFile); + const reportPath = Util.relativePath(htmlPath); + if (saveReportPath) { + reportData[saveReportPath] = reportPath; + } + + // report data + const reportDataCompressed = deflateSync(JSON.stringify(reportData)); + const reportDataStr = `window.reportData = '${reportDataCompressed}';`; + + // js libs + const jsList = []; + + // deps + jsFiles.forEach((id) => { + jsList.push({ + filename: `${id}.js`, + str: Assets.getFileContent(id) + }); + }); + + // html content + let htmlStr = ''; + const EOL = Util.getEOL(); + if (inline) { + htmlStr = [ + '' + ].join(EOL); + } else { + + await Util.writeFile(path.resolve(outputDir, reportDataFile), reportDataStr); + + const assetsDir = path.resolve(outputDir, assetsPath); + const relAssetsDir = Util.relativePath(assetsDir, outputDir); + + for (const item of jsList) { + const filePath = path.resolve(assetsDir, item.filename); + if (!fs.existsSync(filePath)) { + await Util.writeFile(filePath, item.str); + } + } + + htmlStr = [ + ``, + ... jsList.map((it) => ``) + ].join(EOL); + } + + // html + const template = Assets.getFileContent('template'); + const html = Util.replace(template, { + title: reportData.title, + content: htmlStr + }); + + await Util.writeFile(htmlPath, html); + + return reportPath; + } +}; + +module.exports = Assets; diff --git a/node_modules/monocart-coverage-reports/lib/cli.js b/node_modules/monocart-coverage-reports/lib/cli.js new file mode 100755 index 0000000..caae0ac --- /dev/null +++ b/node_modules/monocart-coverage-reports/lib/cli.js @@ -0,0 +1,251 @@ +#!/usr/bin/env node + +const path = require('path'); +const EC = require('eight-colors'); + +const { program } = require('commander'); +const { foregroundChild } = require('foreground-child'); + +const MCR = require('./index.js'); +const Util = require('./utils/util.js'); + +const version = require('../package.json').version; + +const getRegisterPath = (filename) => { + const rel = Util.relativePath(path.resolve(__dirname, 'register', filename)); + if (rel.startsWith('.')) { + return rel; + } + return `./${rel}`; +}; + +const getInitNodeOptions = async (cliOptions) => { + const nodeOptions = []; + if (process.env.NODE_OPTIONS) { + nodeOptions.push(process.env.NODE_OPTIONS); + } + + if (cliOptions.import) { + nodeOptions.push(`--import ${cliOptions.import}`); + // for load mcr.config.ts + await import(cliOptions.import); + } else if (cliOptions.require) { + nodeOptions.push(`--require ${cliOptions.require}`); + // for load mcr.config.ts + await import(cliOptions.require); + } + + return nodeOptions; +}; + +const getPreloadType = (nodeOptions) => { + const hasImport = nodeOptions.find((it) => it.includes('--import')); + if (hasImport) { + return '--import'; + } + return '--require'; +}; + +const checkRegisterFeature = () => { + const nv = process.versions.node; + + // "module.register" added in Node.js: v20.6.0 + // if (Util.cmpVersion(nv, '20.6.0') >= 0) { + // return true; + // } + // but also added in: v18.19.0 + const requiredNV = '18.19.0'; + if (Util.cmpVersion(nv, requiredNV) < 0) { + Util.logInfo(`The current Node.js version "${nv}" does NOT support "module.register", it requires "${requiredNV}" or higher.`); + return false; + } + + // could be < 20.6.0 but just ignore it, please using latest minor version + + return true; +}; + +const loadEnv = (cliOptions) => { + if (!cliOptions.env) { + return; + } + const envFile = cliOptions.env === true ? '.env' : cliOptions.env; + const loadEnvFile = process.loadEnvFile; + if (typeof loadEnvFile === 'function') { + loadEnvFile(envFile); + } +}; + +const initNodeOptions = async (cliOptions) => { + + loadEnv(cliOptions); + + const supportRegister = checkRegisterFeature(); + if (!supportRegister) { + return; + } + + const nodeOptions = await getInitNodeOptions(cliOptions); + // console.log(nodeOptions); + + const preloadType = getPreloadType(nodeOptions); + + // export source after + if (preloadType === '--import') { + const importPath = getRegisterPath('register.mjs'); + nodeOptions.unshift(`--import ${importPath}`); + } else { + const requirePath = getRegisterPath('register.js'); + nodeOptions.unshift(`--require ${requirePath}`); + } + + // console.log(nodeOptions); + const nodeOptionsStr = nodeOptions.join(' '); + Util.logDebug(`node options: ${EC.cyan(nodeOptionsStr)}`); + + process.env.NODE_OPTIONS = nodeOptionsStr; + +}; + +const initNodeV8CoverageDir = (coverageOptions) => { + // dir for node v8 coverage + const nodeV8CoverageDir = Util.relativePath(path.resolve(coverageOptions.outputDir, '.v8-coverage')); + process.env.NODE_V8_COVERAGE = nodeV8CoverageDir; + // clean v8 cache before running + Util.rmSync(nodeV8CoverageDir); + // Util.logInfo(`V8 coverage dir: ${EC.cyan(nodeV8CoverageDir)}`); + + return nodeV8CoverageDir; +}; + +const mergeCoverage = async (cliOptions) => { + const coverageReport = MCR(cliOptions); + await coverageReport.loadConfig(cliOptions.config); + coverageReport.cleanCache(); + await coverageReport.generate(); +}; + +const executeCommand = async (command, cliOptions) => { + + Util.logInfo(`Execute: ${EC.cyan(command)}`); + + if (command === 'merge') { + return mergeCoverage(cliOptions); + } + + // before load config + await initNodeOptions(cliOptions); + + // console.log(options); + const coverageReport = MCR(cliOptions); + await coverageReport.loadConfig(cliOptions.config); + coverageReport.cleanCache(); + + const coverageOptions = coverageReport.options; + const nodeV8CoverageDir = initNodeV8CoverageDir(coverageOptions); + + // ========================================= + // onStart hook + const onStart = coverageOptions.onStart; + if (typeof onStart === 'function') { + await onStart(coverageReport); + } + // ========================================= + + const subprocess = foregroundChild(command, { + shell: true + }, async (code, signal) => { + + // generate coverage even it is failed. code != 0 + + // ========================================= + // onReady hook before adding coverage data. + // Sometimes, the child process has not yet finished writing the coverage data, and it needs to wait here. + const onReady = coverageOptions.onReady; + if (typeof onReady === 'function') { + await onReady(coverageReport, nodeV8CoverageDir, subprocess); + } + // ========================================= + + await coverageReport.addFromDir(nodeV8CoverageDir); + await coverageReport.generate(); + + // remove nodeV8CoverageDir + if (!Util.isDebug()) { + Util.rmSync(nodeV8CoverageDir); + } + + return process.exitCode; + }); + +}; + +process.on('uncaughtException', function(err) { + Util.logError(`Process uncaughtException: ${err.message}`); + console.log(err.stack); +}); + +// the -- separator +const argv = []; +const subArgv = []; +let separator = false; +process.argv.forEach((it) => { + if (!separator && it === '--') { + separator = true; + } + if (separator) { + subArgv.push(it); + } else { + argv.push(it); + } +}); + +program + .name('mcr') + .description('CLI to generate coverage reports') + .version(version, '-v, --version', 'output the current version') + .argument('[command]', 'command to execute') + .allowUnknownOption() + .allowExcessArguments() + .option('-c, --config ', 'custom config file path') + .option('-l, --logging ', 'off, error, info, debug') + + .option('-n, --name ', 'report name for title') + .option('-r, --reports ', 'coverage reports to use') + + .option('-o, --outputDir ', 'output dir for reports') + .option('-i, --inputDir ', 'input dir for merging raw files') + .option('-b, --baseDir ', 'base dir for normalizing path') + + .option('-a, --all ', 'include all files from dir') + + .option('--entryFilter ', 'entry url filter') + .option('--sourceFilter ', 'source path filter') + .option('--filter ', 'the combined filter') + + .option('--outputFile ', 'output file for v8 report') + .option('--inline', 'inline html for v8 report') + .option('--assetsPath ', 'assets path if not inline') + + .option('--lcov', 'generate lcov.info file') + + .option('--import ', 'preload module at startup') + .option('--require ', 'preload module at startup') + + .option('--env [path]', 'env file (default: ".env")') + + .action((_command, cliOptions) => { + const args = [].concat(program.args).concat(subArgv); + if (args[0] === '--') { + args.shift(); + } + const command = args.join(' ').trim(); + if (!command) { + program.outputHelp(); + return; + } + + executeCommand(command, cliOptions); + }); + +program.parse(argv); diff --git a/node_modules/monocart-coverage-reports/lib/client/cdp-client.js b/node_modules/monocart-coverage-reports/lib/client/cdp-client.js new file mode 100644 index 0000000..c91efaf --- /dev/null +++ b/node_modules/monocart-coverage-reports/lib/client/cdp-client.js @@ -0,0 +1,143 @@ + +const EC = require('eight-colors'); + +const { WebSocket } = require('../packages/monocart-coverage-vendor.js'); +const Util = require('../utils/util.js'); + +const WSSession = require('./ws-session.js'); +const CoverageClient = require('./coverage-client.js'); + +const getDebuggerUrl = async (options) => { + + const protocol = options.secure ? 'https' : 'http'; + + const url = `${protocol}://${options.host}:${options.port}/json/list`; + const [err, res] = await Util.request(url); + if (err) { + return [err]; + } + + const targets = res.data; + if (!Util.isList(targets)) { + return [new Error(`Invalid response data: ${url}`)]; + } + + // console.log(targets); + const target = options.target(targets); + if (!target) { + return [new Error(`Not found target: ${url}`)]; + } + + return [null, target.webSocketDebuggerUrl]; +}; + +const getCDPUrl = async (options) => { + if (options.url) { + return [null, options.url]; + } + + // get debugger url + const [err, debuggerUrl] = await getDebuggerUrl(options); + if (err) { + return [err]; + } + + return [null, debuggerUrl]; + +}; + +const getCDPSession = async (options) => { + + if (options.session) { + return [null, options.session]; + } + + // create session + const [err, url] = await getCDPUrl(options); + + return new Promise((resolve) => { + + if (err) { + resolve([err]); + return; + } + + const timeoutId = setTimeout(() => { + resolve([new Error(`Timeout to connect: ${url}`)]); + }, options.timeout); + + Util.logDebug(`Connect to ${url}`); + const ws = new WebSocket(url, [], { + maxPayload: 256 * 1024 * 1024, + perMessageDeflate: false, + followRedirects: true, + ... options.ws + }); + + ws.once('error', (wsErr) => { + clearTimeout(timeoutId); + resolve([wsErr]); + }); + + ws.once('open', () => { + clearTimeout(timeoutId); + Util.logDebug(`${EC.green('Connected')} ${url}`); + const session = new WSSession(ws); + resolve([null, session]); + }); + + }); + + +}; + + +const CDPClient = async (cdpOptions) => { + + const defaultOptions = { + session: null, + url: null, + port: 9222, + host: 'localhost', + secure: false, + target: (targets) => { + // defaults to first page + const page = targets.find((it) => it.webSocketDebuggerUrl && it.type === 'page'); + if (page) { + return page; + } + return targets.find((it) => it.webSocketDebuggerUrl); + }, + ws: {}, + timeout: 10 * 1000 + }; + + if (typeof cdpOptions === 'string') { + cdpOptions = { + url: cdpOptions + }; + } + + const options = { + ... defaultOptions, + ... cdpOptions + }; + + const [err, session] = await getCDPSession(options); + + return new Promise((resolve) => { + + if (err) { + Util.logError(err); + resolve(); + return; + } + + const helper = new CoverageClient(session); + resolve(helper); + + }); + +}; + +module.exports = CDPClient; diff --git a/node_modules/monocart-coverage-reports/lib/client/coverage-client.js b/node_modules/monocart-coverage-reports/lib/client/coverage-client.js new file mode 100644 index 0000000..c6e2d65 --- /dev/null +++ b/node_modules/monocart-coverage-reports/lib/client/coverage-client.js @@ -0,0 +1,322 @@ +const Util = require('../utils/util.js'); + +const bindEvents = (target, events) => { + Object.keys(events).forEach((eventType) => { + target.on(eventType, events[eventType]); + }); +}; + +const unbindEvents = (target, events) => { + Object.keys(events).forEach((eventType) => { + target.off(eventType, events[eventType]); + }); +}; + +// keep same ranges with playwright +// eslint-disable-next-line complexity +const convertToDisjointRanges = (nestedRanges) => { + const points = []; + for (const range of nestedRanges) { + points.push({ + offset: range.start, + type: 0, + range + }); + points.push({ + offset: range.end, + type: 1, + range + }); + } + // Sort points to form a valid parenthesis sequence. + points.sort((a, b) => { + // Sort with increasing offsets. + if (a.offset !== b.offset) { + return a.offset - b.offset; + } + // All "end" points should go before "start" points. + if (a.type !== b.type) { + return b.type - a.type; + } + const aLength = a.range.end - a.range.start; + const bLength = b.range.end - b.range.start; + // For two "start" points, the one with longer range goes first. + if (a.type === 0) { + return bLength - aLength; + } + // For two "end" points, the one with shorter range goes first. + return aLength - bLength; + }); + + const hitCountStack = []; + const results = []; + let lastOffset = 0; + // Run scanning line to intersect all ranges. + for (const point of points) { + if (hitCountStack.length && lastOffset < point.offset && hitCountStack[hitCountStack.length - 1] > 0) { + const lastResult = results.length ? results[results.length - 1] : null; + if (lastResult && lastResult.end === lastOffset) { + lastResult.end = point.offset; + } else { + results.push({ + start: lastOffset, + end: point.offset + }); + } + } + lastOffset = point.offset; + if (point.type === 0) { + hitCountStack.push(point.range.count); + } else { + hitCountStack.pop(); + } + } + // Filter out empty ranges. + return results.filter((range) => range.end - range.start > 1); +}; + +class CoverageClient { + constructor(session) { + this.session = session; + } + + // ================================================================================================= + async startJSCoverage() { + if (!this.session || this.enabledJS) { + return; + } + this.enabledJS = true; + this.scriptSources = new Map(); + this.jsEvents = { + 'Debugger.scriptParsed': (params) => { + const { scriptId } = params; + this.session.send('Debugger.getScriptSource', { + scriptId + }).then((res) => { + this.scriptSources.set(scriptId, res && res.scriptSource); + }); + }, + 'Debugger.paused': () => { + this.send('Debugger.resume'); + } + }; + + bindEvents(this.session, this.jsEvents); + + await this.session.send('Debugger.enable'); + await this.session.send('Debugger.setSkipAllPauses', { + skip: true + }); + + await this.session.send('Profiler.enable'); + await this.session.send('Profiler.startPreciseCoverage', { + callCount: true, + detailed: true + }); + + // Util.logDebug('startJSCoverage'); + + } + + async stopJSCoverage() { + if (!this.session || !this.enabledJS) { + return; + } + + const profileResponse = await this.session.send('Profiler.takePreciseCoverage'); + await this.session.send('Profiler.stopPreciseCoverage'); + await this.session.send('Profiler.disable'); + // await this.session.send('Debugger.disable'); + + unbindEvents(this.session, this.jsEvents); + this.jsEvents = null; + + const jsCoverage = []; + + // console.log('coverageList', coverageList); + if (profileResponse && profileResponse.result) { + profileResponse.result.forEach((entry) => { + // anonymous url + entry.url = entry.url || ''; + // add source + const source = this.scriptSources.get(entry.scriptId); + if (!source) { + Util.logDebug(`Not found js source: ${entry.url}`); + } + entry.source = source || ''; + jsCoverage.push(entry); + }); + } + + this.scriptSources.clear(); + this.enabledJS = false; + + return jsCoverage; + } + + // ================================================================================================= + + async startCSSCoverage() { + if (!this.session || this.enabledCSS) { + return; + } + this.enabledCSS = true; + this.styleEntries = new Map(); + + this.cssEvents = { + 'CSS.styleSheetAdded': (e) => { + const { sourceURL, styleSheetId } = e.header; + + // anonymous url + const url = sourceURL || ''; + this.session.send('CSS.getStyleSheetText', { + styleSheetId + }).then((res) => { + // add source + const text = res && res.text; + if (!text) { + Util.logDebug(`Not found css source: ${url}`); + } + this.styleEntries.set(styleSheetId, { + url, + text: text || '', + ranges: [] + }); + }); + } + }; + + bindEvents(this.session, this.cssEvents); + + await this.session.send('DOM.enable'); + await this.session.send('CSS.enable'); + await this.session.send('CSS.startRuleUsageTracking'); + + // Util.logDebug('startCSSCoverage'); + } + + async stopCSSCoverage() { + if (!this.session || !this.enabledCSS) { + return; + } + + const ruleTrackingResponse = await this.session.send('CSS.stopRuleUsageTracking'); + await this.session.send('CSS.disable'); + await this.session.send('DOM.disable'); + + unbindEvents(this.session, this.cssEvents); + this.cssEvents = null; + + const cssCoverage = []; + + if (ruleTrackingResponse) { + for (const usage of ruleTrackingResponse.ruleUsage) { + const entry = this.styleEntries.get(usage.styleSheetId); + if (entry) { + entry.ranges.push({ + start: usage.startOffset, + end: usage.endOffset, + count: usage.used ? 1 : 0 + }); + } + } + this.styleEntries.forEach((entry) => { + entry.ranges = convertToDisjointRanges(entry.ranges); + cssCoverage.push(entry); + }); + } + + this.styleEntries.clear(); + this.enabledCSS = false; + + return cssCoverage; + } + + // ================================================================================================= + + async startCoverage() { + await Promise.all([ + this.startJSCoverage(), + this.startCSSCoverage() + ]); + } + + async stopCoverage() { + if (!this.session) { + return; + } + const [jsCoverage, cssCoverage] = await Promise.all([ + this.stopJSCoverage(), + this.stopCSSCoverage() + ]); + // could be undefined + let coverageList = []; + if (jsCoverage) { + coverageList = coverageList.concat(jsCoverage); + } + if (cssCoverage) { + coverageList = coverageList.concat(cssCoverage); + } + return coverageList; + } + + // ================================================================================================= + // write the coverage started by NODE_V8_COVERAGE to disk on demand + async writeCoverage() { + if (!this.session) { + return; + } + + await this.session.send('Runtime.enable'); + + // write the coverage started by NODE_V8_COVERAGE to disk on demand + const res = await this.session.send('Runtime.evaluate', { + expression: `new Promise((resolve) => { + require("v8").takeCoverage(); + resolve(process.env.NODE_V8_COVERAGE); + })`, + includeCommandLineAPI: true, + returnByValue: true, + awaitPromise: true + }); + + await this.session.send('Runtime.disable'); + + return res && res.result && res.result.value; + } + + // get istanbul coverage data + async getIstanbulCoverage(coverageKey = '__coverage__') { + if (!this.session) { + return; + } + + await this.session.send('Runtime.enable'); + + // both browser and Node.js + const res = await this.session.send('Runtime.evaluate', { + expression: `new Promise((resolve) => { + const globalTarget = typeof window !== 'undefined' ? window : global; + resolve(globalTarget['${coverageKey}']); + })`, + includeCommandLineAPI: true, + returnByValue: true, + awaitPromise: true + }); + + await this.session.send('Runtime.disable'); + + return res && res.result && res.result.value; + } + + // ================================================================================================= + async close() { + if (!this.session) { + return; + } + await this.session.detach(); + this.session = null; + } +} + +module.exports = CoverageClient; diff --git a/node_modules/monocart-coverage-reports/lib/client/ws-session.js b/node_modules/monocart-coverage-reports/lib/client/ws-session.js new file mode 100644 index 0000000..cb35ad3 --- /dev/null +++ b/node_modules/monocart-coverage-reports/lib/client/ws-session.js @@ -0,0 +1,63 @@ +const { EventEmitter } = require('events'); + +class WSSession extends EventEmitter { + constructor(ws) { + super(); + this.ws = ws; + this.requestId = 1; + this.requestCache = new Map(); + ws.on('message', (data, isBinary) => { + + const message = JSON.parse(data); + // console.log(message); + + const { id, method } = message; + if (id) { + const request = this.requestCache.get(id); + this.requestCache.delete(id); + if (request) { + request.resolve(message.result); + } + return; + } + + if (method) { + this.emit(method, message.params, message.sessionId); + } + + }); + } + + send(method, params) { + return new Promise((resolve, reject) => { + if (!this.ws) { + reject(new Error('Invalid websocket')); + return; + } + const id = this.requestId++; + const message = { + id, + method, + params: params || {} + }; + this.ws.send(JSON.stringify(message), (err) => { + if (err) { + reject(err); + return; + } + this.requestCache.set(id, { + resolve + }); + }); + }); + } + + detach() { + if (this.ws) { + this.ws.terminate(); + this.ws = null; + } + } +} + +module.exports = WSSession; diff --git a/node_modules/monocart-coverage-reports/lib/converter/ast-visitor.js b/node_modules/monocart-coverage-reports/lib/converter/ast-visitor.js new file mode 100644 index 0000000..b25fb5b --- /dev/null +++ b/node_modules/monocart-coverage-reports/lib/converter/ast-visitor.js @@ -0,0 +1,809 @@ +const Util = require('../utils/util.js'); + +const BranchTypes = { + ConditionalExpression: 'ConditionalExpression', + LogicalExpression: 'LogicalExpression', + IfStatement: 'IfStatement', + SwitchStatement: 'SwitchStatement', + AssignmentPattern: 'AssignmentPattern' +}; + +const setGeneratedOnly = (block, generatedOnly) => { + if (block && generatedOnly) { + block.generatedOnly = true; + } +}; + +const getParentFunctionState = (reverseParents) => { + const parentFunction = reverseParents.find((it) => it._state && it._state.isFunction); + if (!parentFunction) { + return; + } + return parentFunction._state; +}; + +const getParentCount = (reverseParents, functionCount) => { + // parent count + const parent = reverseParents.find((it) => it._state); + if (parent) { + return parent._state.count; + } + // root function count + return functionCount; +}; + +const getFunctionRange = (start, end, type, coverageInfo) => { + + const { + functionMap, functionNameMap, functionStaticRanges, functionUncoveredRanges + } = coverageInfo; + + // exact matched in functionMap + const range = functionMap.get(start); + if (range) { + return range; + } + // exact matched in functionNameMap + const nameRange = functionNameMap.get(start); + if (nameRange) { + return nameRange; + } + + if (type === 'StaticBlock' && functionStaticRanges.length) { + const staticRange = Util.findInRanges(start, end, functionStaticRanges, 'startOffset', 'endOffset'); + if (staticRange) { + return staticRange; + } + } + + // find in uncoveredRanges + return Util.findInRanges(start, end, functionUncoveredRanges, 'startOffset', 'endOffset'); +}; + +const getFunctionBlock = (start, end, functionState) => { + if (!functionState) { + return; + } + + const { range } = functionState; + if (!range) { + return; + } + + const { + blockMap, blockUncoveredRanges, blockCoveredRanges + } = range; + + if (!blockMap) { + return; + } + + const block = blockMap.get(start); + if (block) { + return block; + } + + const uncoveredBlock = Util.findInRanges(start, end, blockUncoveredRanges, 'startOffset', 'endOffset'); + if (uncoveredBlock) { + return uncoveredBlock; + } + + // the block is not exact correct, if there is a block wrapped + // [x8]{ var a = b || [x4]c }, b is no block, but it can be found in x8 block + const coveredBlocks = blockCoveredRanges.filter((it) => start >= it.startOffset && end <= it.endOffset); + if (coveredBlocks.length) { + return coveredBlocks.pop(); + } + +}; + +const addNodeCount = (item) => { + + const { node, reverseParents } = item; + + if (node._state) { + return; + } + + const { start, end } = node; + const functionState = getParentFunctionState(reverseParents); + const block = getFunctionBlock(start, end, functionState); + if (block) { + node._state = { + count: block.count + }; + } + +}; + +// ======================================================================================= + +const createBranchGroup = (type, node, parents, branchMap) => { + const { start, end } = node; + // clone and reverse parents + const reverseParents = [].concat(parents).reverse(); + const group = { + type, + + start, + // could be updated if multiple locations + end, + + locations: [], + reverseParents + }; + + if (type === BranchTypes.LogicalExpression) { + // && or || + group.operator = node.operator; + } + + // could be same start + const branchKey = `${start}_${end}`; + + branchMap.set(branchKey, group); + return group; +}; + +const addBranch = (group, node, locationMap) => { + const { + start, end, type + } = node; + + const branchKey = `${group.start}_${group.end}`; + + const branchInfo = { + // for get previous group for LogicalExpression + branchKey, + start, + end, + // branch count default to 0 + count: 0 + }; + + if (type === 'SwitchCase') { + + // console.log(node); + + // check break + if (node.consequent) { + const breakItem = node.consequent.find((it) => it.type === 'BreakStatement'); + if (breakItem) { + branchInfo.hasBreak = true; + } + } + + // check default + if (!node.test) { + branchInfo.isDefault = true; + } + } + + group.locations.push(branchInfo); + + // update group end + if (end > group.end) { + group.end = end; + } + + locationMap.set(start, branchInfo); + + return branchInfo; +}; + +const addNoneBranch = (group) => { + group.locations.push({ + none: true, + count: 0 + }); +}; + +// ======================================================================================= + +const updateBlockLocations = (locations) => { + const noBlockList = []; + let blockCount = 0; + locations.forEach((item, i) => { + if (item.block) { + item.count = item.block.count; + blockCount += item.count; + return; + } + // for calculate mo break branches + item.index = i; + noBlockList.push(item); + }); + + return { + noBlockList, + blockCount + }; +}; + +// const a = tf1 ? 'true' : 'false'; +const ConditionalExpression = (group, parentCount) => { + const { noBlockList, blockCount } = updateBlockLocations(group.locations); + if (!noBlockList.length) { + return; + } + let count = parentCount - blockCount; + noBlockList.forEach((item) => { + item.count = count; + count = 0; + }); +}; + +const IfStatement = (group, parentCount) => { + const { noBlockList, blockCount } = updateBlockLocations(group.locations); + if (!noBlockList.length) { + return; + } + // console.log(parentCount, 'uncovered list', noBlockList.length, group.start); + let count = parentCount - blockCount; + noBlockList.forEach((item) => { + item.count = count; + count = 0; + }); + +}; + +// const b = tf2 || tf1 || a; +const LogicalExpression = (group, parentCount) => { + + // from left to right + group.locations.forEach((item, i) => { + if (item.block) { + item.count = item.block.count; + } else { + item.count = parentCount; + } + }); + +}; + +const SwitchStatement = (group, parentCount) => { + + const locations = group.locations; + + const { noBlockList, blockCount } = updateBlockLocations(locations); + if (!noBlockList.length) { + return; + } + + // calculate switch/case count + const countLeft = parentCount - blockCount; + noBlockList.forEach((item) => { + + let hasCount = false; + + // check no break branches + for (let i = item.index - 1; i >= 0; i--) { + const b = locations[i]; + if (b && !b.hasBreak && b.count > 0) { + item.count += b.count; + hasCount = true; + continue; + } + break; + } + + if (!hasCount) { + item.count = countLeft; + } + }); +}; + +const AssignmentPattern = (group, parentCount) => { + group.locations.forEach((item) => { + item.count = parentCount; + }); +}; + +// ======================================================================================= + +const updateBranchCount = (group) => { + + const { + type, locations, reverseParents + } = group; + + const functionState = getParentFunctionState(reverseParents); + + const functionCount = functionState.count; + + // default is 0, no need continue + if (functionCount === 0) { + return; + } + + // parent is block statement or function + let parentCount = getParentCount(reverseParents, functionCount); + // parent is group range + const groupBlock = getFunctionBlock(group.start, group.end, functionState); + if (groupBlock) { + parentCount = groupBlock.count; + setGeneratedOnly(groupBlock, group.generatedOnly); + } + + // calculate branches count + locations.forEach((item) => { + const { + start, end, none + } = item; + if (none) { + return; + } + + item.block = getFunctionBlock(start, end, functionState); + setGeneratedOnly(item.block, group.generatedOnly); + + }); + + + const handlers = { + ConditionalExpression, + LogicalExpression, + IfStatement, + SwitchStatement, + AssignmentPattern + }; + + const handler = handlers[type]; + if (handler) { + handler(group, parentCount); + } + +}; + +const generateBranches = (branchMap) => { + + // calculate count for all branches + branchMap.forEach((group) => { + updateBranchCount(group); + }); + + // init branches + const branches = []; + branchMap.forEach((group) => { + + // add start/end for none with group start/end + group.locations.forEach((item) => { + if (item.none) { + item.start = group.start; + item.end = group.end; + } + }); + + const branch = { + type: group.type, + start: group.start, + end: group.end, + locations: group.locations + }; + + setGeneratedOnly(branch, group.generatedOnly); + + branches.push(branch); + }); + + // sort branches + branches.sort((a, b) => { + return a.start - b.start; + }); + + return branches; +}; + +// ======================================================================================= +// All programs in JavaScript are made of statements and they end with semicolons (;) except block statements which is used to group zero or more statements. +// Statements are just perform some actions but do not produce any value or output whereas expressions return some value. +// Expressions return value, statements do not. +const generateStatements = (statementNodes) => { + + statementNodes.forEach((item) => { + const { + node, + reverseParents + } = item; + + const { start, end } = node; + + item.count = 1; + + // isFunction + if (node._state) { + item.count = node._state.count; + return; + } + + const functionState = getParentFunctionState(reverseParents); + if (!functionState) { + // there is a root range, it impossible not found + return; + } + + // function uncovered + if (functionState.count === 0) { + item.count = 0; + return; + } + + const block = getFunctionBlock(start, end, functionState); + if (block) { + item.count = block.count; + return; + } + + item.count = functionState.count; + + }); + + // remove block statement + statementNodes = statementNodes.filter((item) => { + return item.node.type !== 'BlockStatement'; + }); + + const statements = statementNodes.map((item) => { + const { + node, + count + } = item; + const { start, end } = node; + return { + start, + end, + count + }; + }); + + return statements; +}; + +// ======================================================================================= +// handle special generated codes for original coverage + +const webpackWrapHandler = (node) => { + // ignore webpack wrap for original function + // id: { type: 'Identifier', name: '__webpack_modules__' }, + const name = node.id && node.id.name; + if (name === '__webpack_modules__' && node.init && node.init.properties) { + // mark all as wrap function + node.init.properties.forEach((it) => { + it.value._webpackWrapKey = it.key && it.key.value; + }); + // console.log('==========================', node.type); + // console.log(name, parents.length); + } +}; + +const viteImportDefaultHandler = (node, group) => { + // ignore vite conditional expression for __esModule default + const testObj = node.test.object; + const testName = testObj && testObj.name; + if (testName && testName.startsWith('__vite__cjsImport')) { + setGeneratedOnly(group, true); + } + +}; + + +// ======================================================================================= + +const collectNodes = (ast) => { + const functionNodes = []; + const statementNodes = []; + const blockNodes = []; + const branchMap = new Map(); + // locationMap for chain LogicalExpression locations + const locationMap = new Map(); + + Util.visitAst(ast, { + + VariableDeclarator(node, parents) { + + webpackWrapHandler(node); + + }, + + // =============================================================================== + // statements + + Statement: (node, parents) => { + const reverseParents = [].concat(parents).reverse(); + statementNodes.push({ + node, + reverseParents + }); + }, + + // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes/static + // as a function "functionName": "", + StaticBlock: (node, parents) => { + const reverseParents = [].concat(parents).reverse(); + functionNodes.push({ + node, + reverseParents + }); + }, + + // =============================================================================== + // functions + // Function include FunctionDeclaration, ArrowFunctionExpression, FunctionExpression + Function(node, parents) { + const reverseParents = [].concat(parents).reverse(); + functionNodes.push({ + node, + reverseParents + }); + }, + + // =============================================================================== + // branches + + // `for` block, the count not equal to parent + BlockStatement: (node, parents) => { + + // fix branch count: BRDA + const reverseParents = [].concat(parents).reverse(); + blockNodes.push({ + node, + reverseParents + }); + + }, + + // default-arg assignment logic. + // function default arguments + AssignmentPattern: (node, parents) => { + const group = createBranchGroup(BranchTypes.AssignmentPattern, node, parents, branchMap); + addBranch(group, node, locationMap); + }, + + // cond-expr a ternary expression. e.g.: x ? y : z + // Ternary + // var b = a ? 'consequent' : 'alternate'; + ConditionalExpression: (node, parents) => { + + const { consequent, alternate } = node; + const group = createBranchGroup(BranchTypes.ConditionalExpression, node, parents, branchMap); + addBranch(group, consequent, locationMap); + addBranch(group, alternate, locationMap); + + viteImportDefaultHandler(node, group); + + }, + + // if an if statement; can also be else if. + // An IF statement always has exactly two branches: + // one where the condition is FALSE and one where the condition is TRUE + IfStatement: (node, parents) => { + const { consequent, alternate } = node; + const group = createBranchGroup(BranchTypes.IfStatement, node, parents, branchMap); + addBranch(group, consequent, locationMap); + + // console.log('if type', consequent.type); + + if (alternate) { + addBranch(group, alternate, locationMap); + } else { + // add none branch + addNoneBranch(group); + // no need update group end, there is no end + } + }, + + // binary-expr a logical expression with a binary operand. e.g.: x && y + // var b = a || b || c; + // do not use BinaryExpression + LogicalExpression: (node, parents) => { + const { left, right } = node; + // console.log(left.start, right.start); + + // could be same branch start + // const da = arguments.length > 1 && typeof arguments[1] !== 'undefined' ? arguments[1] : true; + + let group; + // link to same branch start if LogicalExpression + const prevLocation = locationMap.get(node.start); + if (prevLocation) { + // console.log('link branch ==================', type); + group = branchMap.get(prevLocation.branchKey); + } else { + group = createBranchGroup(BranchTypes.LogicalExpression, node, parents, branchMap); + addBranch(group, left, locationMap); + } + + addBranch(group, right, locationMap); + + // console.log(group.locations.map((it) => it.start)); + + // sort branch locations + // a || b || c + // first, left a and right c + // then, left a and right b + if (prevLocation) { + const { locations } = group; + locations.sort((a, b) => { + return a.start - b.start; + }); + // update group end after sorted + const lastEnd = locations[locations.length - 1].end; + if (lastEnd > group.end) { + group.end = lastEnd; + } + } + }, + + // switch a switch statement. + SwitchStatement: (node, parents) => { + const group = createBranchGroup(BranchTypes.SwitchStatement, node, parents, branchMap); + const cases = node.cases; + cases.forEach((switchCase) => { + // console.log('switchCase', switchCase.start); + addBranch(group, switchCase, locationMap); + }); + } + + }); + + return { + functionNodes, + statementNodes, + blockNodes, + branchMap + }; +}; + +const getRootFunctionState = (ast, coverageInfo) => { + const rootState = { + isFunction: true, + count: 1 + }; + const rootRange = coverageInfo.rootRange; + if (rootRange) { + rootState.range = rootRange; + rootState.count = rootRange.count; + + // could be not from 0 + // 0 881 { startOffset: 77, endOffset: 881, + // const { start, end } = ast; + // console.log(start, end, rootRange); + + } + ast._state = rootState; + + return rootState; +}; + +// eslint-disable-next-line complexity +const findFunctionRange = (item, coverageInfo) => { + + const { node, reverseParents } = item; + const { + start, end, type + } = node; + + // try function start/end + const functionRange = getFunctionRange(start, end, type, coverageInfo); + if (functionRange) { + return functionRange; + } + + // `static async` case: + // [1]static [2]async [3]covered(active) { + // v8 start: 2 + // ast start: 1,3 + + // fixed by async or static + + // handle for static async + if (node.async) { + // 'async '.length + const asyncLen = 6; + const asyncStart = start - asyncLen; + // console.log(asyncStart, 'asyncStart ==============================================='); + const asyncRange = getFunctionRange(asyncStart, end, type, coverageInfo); + if (asyncRange) { + return asyncRange; + } + } + + // try if class MethodDefinition + // 0 is function self + const parent = reverseParents[1]; + if (parent && parent.type === 'MethodDefinition') { + + const parentRange = getFunctionRange(parent.start, parent.end, parent.type, coverageInfo); + if (parentRange) { + return parentRange; + } + + if (parent.static) { + // 'static '.length + const staticLen = 7; + const staticStart = parent.start + staticLen; + // console.log(staticStart, ' staticStart ============================================'); + const staticRange = getFunctionRange(staticStart, parent.end, parent.type, coverageInfo); + if (staticRange) { + return staticRange; + } + } + + } + + +}; + +const collectAstInfo = (ast, coverageInfo) => { + + const { + functionNodes, statementNodes, blockNodes, branchMap + } = collectNodes(ast); + + // root function state + const rootState = getRootFunctionState(ast, coverageInfo); + + const functions = []; + functionNodes.forEach((item) => { + const { node } = item; + const { + start, end, id + } = node; + + const bodyStart = node.body.start; + const bodyEnd = node.body.end; + const functionName = id && id.name; + const _webpackWrapKey = node._webpackWrapKey; + + const functionItem = { + start, + end, + bodyStart, + bodyEnd, + functionName, + count: rootState.count + }; + + setGeneratedOnly(functionItem, _webpackWrapKey); + + functions.push(functionItem); + + const functionState = { + isFunction: true, + count: functionItem.count + }; + + const functionRange = findFunctionRange(item, coverageInfo); + if (functionRange) { + + setGeneratedOnly(functionRange, _webpackWrapKey); + + functionState.range = functionRange; + functionState.count = functionRange.count; + functionItem.count = functionRange.count; + } + node._state = functionState; + + // console.log(item.reverseParents.map((it) => it.type)); + + }); + + blockNodes.forEach((item) => { + addNodeCount(item); + }); + + const branches = generateBranches(branchMap); + const statements = generateStatements(statementNodes); + + return { + functions, + branches, + statements + }; + +}; + +module.exports = { + BranchTypes, + collectAstInfo +}; diff --git a/node_modules/monocart-coverage-reports/lib/converter/ast.js b/node_modules/monocart-coverage-reports/lib/converter/ast.js new file mode 100644 index 0000000..5c7dd70 --- /dev/null +++ b/node_modules/monocart-coverage-reports/lib/converter/ast.js @@ -0,0 +1,364 @@ +const acorn = require('acorn'); +const acornLoose = require('acorn-loose'); +const { parseCss } = require('../packages/monocart-coverage-vendor.js'); +const Util = require('../utils/util.js'); + +const { collectAstInfo } = require('./ast-visitor.js'); + +const getCoverageInfo = (coverageList) => { + const functionMap = new Map(); + const functionNameMap = new Map(); + const functionStaticRanges = []; + const functionUncoveredRanges = []; + + let rootRange; + coverageList.forEach((block) => { + const { + functionName, ranges, root + } = block; + + let functionRange; + const blockRanges = []; + + ranges.forEach((range, i) => { + if (i === 0) { + // function range + functionRange = range; + return; + } + blockRanges.push(range); + }); + + functionRange.functionName = functionName; + + // blocks + if (blockRanges.length) { + const blockMap = new Map(); + blockRanges.forEach((item) => { + blockMap.set(item.startOffset, item); + }); + functionRange.blockMap = blockMap; + // uncovered is unique + const blockUncoveredRanges = blockRanges.filter((it) => it.count === 0); + Util.sortOffsetRanges(blockUncoveredRanges); + functionRange.blockUncoveredRanges = blockUncoveredRanges; + functionRange.blockCoveredRanges = blockRanges.filter((it) => it.count > 0); + } + + // root function from vm + if (root) { + rootRange = functionRange; + return; + } + + // root function from first range + if (!rootRange) { + rootRange = functionRange; + } + + functionMap.set(functionRange.startOffset, functionRange); + if (functionName) { + // can not handle `async functionName` + const possibleNameOffset = functionRange.startOffset + functionName.length; + functionNameMap.set(possibleNameOffset, functionRange); + } + + if (functionName === '') { + functionStaticRanges.push(functionRange); + } + + // cache uncovered + if (functionRange.count === 0) { + functionUncoveredRanges.push(functionRange); + } + + }); + + // sort ranges + Util.sortOffsetRanges(functionUncoveredRanges); + + return { + functionMap, + functionNameMap, + functionStaticRanges, + functionUncoveredRanges, + rootRange + }; + +}; + +const getFakeAstInfo = (coverageList) => { + const functions = []; + const branches = []; + const statements = []; + coverageList.forEach((block) => { + const { + isBlockCoverage, functionName, ranges, root + } = block; + + ranges.forEach((range, i) => { + + const { + startOffset, endOffset, count + } = range; + + if (i === 0 && root) { + return; + } + + statements.push({ + start: startOffset, + end: endOffset, + count + }); + + if (isBlockCoverage) { + // branches + branches.push({ + type: 'branch', + start: startOffset, + end: endOffset, + locations: [{ + start: startOffset, + end: endOffset, + count + }] + }); + } + + if (i === 0) { + // function range + functions.push({ + start: startOffset, + end: endOffset, + bodyStart: startOffset, + bodyEnd: endOffset, + count, + functionName + }); + + } + }); + + }); + + // console.log('fake functions', functions.map((it) => it)); + + return { + functions, + branches, + statements + }; +}; + +const getJsAstInfo = (item, coverageList) => { + + const { + source, fake, empty + } = item; + + if (fake) { + return getFakeAstInfo(coverageList); + } + + const options = { + ecmaVersion: 'latest', + // most time for node.js file + allowReturnOutsideFunction: true, + allowImportExportEverywhere: true, + allowAwaitOutsideFunction: true, + allowSuperOutsideMethod: true, + // first line: #!/usr/bin/env node + allowHashBang: true + }; + + let err; + let ast; + try { + ast = acorn.parse(source, options); + } catch (e) { + err = e; + } + + if (err) { + + // empty = untested file + // could be .ts, .vue and so on, that can not be parsed normally + if (empty) { + return { + functions: [], + branches: [], + statements: [] + }; + } + + // runtime code should be parsed successful + Util.logInfo(`Unparsable source: ${item.sourcePath} ${err.message}`); + + // it could be jsx even it is `.js` + + // https://github.com/acornjs/acorn/tree/master/acorn-loose + // It is recommended to always try a parse with the regular acorn parser first, + // and only fall back to this parser when that one finds syntax errors. + ast = acornLoose.parse(source, options); + + } + + const coverageInfo = getCoverageInfo(coverageList); + coverageInfo.item = item; + + return collectAstInfo(ast, coverageInfo); +}; + +// ========================================================================================================= + +const addRule = (item, coverageList, coveredRanges, count = 0) => { + + const { source } = item; + const { start, end } = source; + const startOffset = start.offset; + const endOffset = end.offset; + + if (!count) { + const coveredRange = Util.findInRanges(startOffset, endOffset, coveredRanges, 'startOffset', 'endOffset'); + if (coveredRange) { + count = 1; + } + } + + coverageList.push({ + start: startOffset, + end: endOffset, + count + }); + + return count; + +}; + +const addAtRule = (item, coverageList, coveredRanges, empty) => { + const { name, nodes } = item; + + const defaultCount = empty ? 0 : 1; + + if (['charset', 'import', 'namespace'].includes(name)) { + addRule(item, coverageList, coveredRanges, defaultCount); + return; + } + + if (['media', 'supports', 'container', 'layer'].includes(name)) { + + const childCoverageList = []; + const count = addCssRules(nodes, childCoverageList, coveredRanges, empty); + if (count) { + + coverageList.push({ + start: item.source.start.offset, + end: childCoverageList[0].start, + count: 1 + }); + + let end; + childCoverageList.forEach((it) => { + coverageList.push(it); + end = it.end; + }); + + coverageList.push({ + start: end, + end: item.source.end.offset, + count: 1 + }); + + return; + } + + } + + addRule(item, coverageList, coveredRanges); + +}; + +const addCssRules = (list, coverageList, coveredRanges, empty) => { + + if (!Util.isList(list)) { + return 0; + } + + let count = 0; + + // line and line is 1-base + list.forEach((item) => { + + const { type } = item; + + if (type === 'comment') { + return; + } + + if (type === 'rule') { + count += addRule(item, coverageList, coveredRanges); + return; + } + + // console.log('============================================================================='); + // Object.keys(item).forEach((k) => { + // if (k === 'parent') { + // return; + // } + // if (k === 'raws') { + // return; + // } + // if (k === 'nodes') { + // console.log(k, item[k].length); + // return; + // } + // if (k === 'source') { + // console.log(k, item[k].start, item[k].end); + // return; + // } + // console.log(k, item[k]); + // }); + + if (type === 'atrule') { + addAtRule(item, coverageList, coveredRanges, empty); + } + + }); + + return count; +}; + +const getCssAstInfo = (item, coverageList) => { + + const { + source, ranges, empty + } = item; + + // sort covered ranges + ranges.sort((a, b) => a.start - b.start); + + // to offset covered ranges + const coveredRanges = ranges.map((it) => { + return { + startOffset: it.start, + endOffset: it.end + }; + }); + + const ast = parseCss(source); + + addCssRules(ast.nodes, coverageList, coveredRanges, empty); + + return { + functions: [], + branches: [], + statements: [] + }; +}; + + +module.exports = { + getJsAstInfo, + getCssAstInfo +}; diff --git a/node_modules/monocart-coverage-reports/lib/converter/collect-source-maps.js b/node_modules/monocart-coverage-reports/lib/converter/collect-source-maps.js new file mode 100644 index 0000000..6d3bcf4 --- /dev/null +++ b/node_modules/monocart-coverage-reports/lib/converter/collect-source-maps.js @@ -0,0 +1,287 @@ +const fs = require('fs'); +const path = require('path'); +const EC = require('eight-colors'); +const { fileURLToPath, pathToFileURL } = require('url'); +const Concurrency = require('../platform/concurrency.js'); +const { convertSourceMap } = require('../packages/monocart-coverage-vendor.js'); +const { flattenSourceMaps } = require('./flatten-source-maps.js'); + +const Util = require('../utils/util.js'); + +const defaultSourceMapResolver = async (url = '') => { + + if (url.startsWith('file:')) { + const p = fileURLToPath(url); + const content = Util.readFileSync(p); + if (!content) { + Util.logDebug(EC.red(`failed to load sourcemap ${p}`)); + return; + } + return Util.jsonParse(content); + } + + const [err, res] = await Util.request(url); + + if (err) { + Util.logDebug(EC.red(`${err.message} ${url}`)); + return; + } + + const content = res.data; + + // could be string not json, if Content-Type is application/octet-stream + if (typeof content === 'string') { + return Util.jsonParse(content); + } + + return content; +}; + +const loadSourceMap = async (url, options) => { + if (typeof options.sourceMapResolver === 'function') { + const content = await options.sourceMapResolver(url, defaultSourceMapResolver); + if (typeof content === 'string') { + return Util.jsonParse(content); + } + return content; + } + return defaultSourceMapResolver(url); +}; + +const getSourceMapUrl = (content, url) => { + + const m = content.match(convertSourceMap.mapFileCommentRegex); + if (!m) { + return; + } + + const comment = m.pop(); + const r = convertSourceMap.mapFileCommentRegex.exec(comment); + // for some odd reason //# .. captures in 1 and /* .. */ in 2 + const filename = r[1] || r[2]; + + const urlObj = Util.resolveUrl(filename, url); + if (urlObj) { + return urlObj.toString(); + } + + const mapUrl = Util.resolveUrl(filename, pathToFileURL(url).toString()); + if (mapUrl) { + return mapUrl.toString(); + } +}; + +const resolveSourcesContent = (data, url) => { + + const { sources, sourcesContent } = data; + + // sources [1,2,3] + // sourcesContent could be [null, null, "content"] + // some of contents could be missed + + let hasSourceContent = false; + sources.forEach((file, i) => { + if (typeof sourcesContent[i] === 'string') { + hasSourceContent = true; + return; + } + + const sourceUrl = Util.resolveUrl(file, url); + if (sourceUrl) { + let sourcePath = sourceUrl.toString(); + // could be no `file:` + if (sourcePath.startsWith('file:')) { + sourcePath = fileURLToPath(sourcePath); + } + const content = Util.readFileSync(path.resolve(sourcePath)); + if (typeof content === 'string') { + sourcesContent[i] = content; + hasSourceContent = true; + return; + } + } + + sourcesContent[i] = ''; + Util.logDebug(EC.red(`failed to load source content: ${file}`)); + + }); + + + if (hasSourceContent) { + return data; + } +}; + +const checkSourcesContent = (data) => { + const { sourcesContent, sources } = data; + + if (!sourcesContent) { + data.sourcesContent = []; + return false; + } + + // all should be string, could be [null] + const contents = sourcesContent.filter((content) => typeof content === 'string'); + if (contents.length === sources.length) { + return true; + } + + return false; +}; + +const resolveSectionedSourceMap = (data, url, sections) => { + + let hasSourceContent = false; + sections.forEach((item) => { + // offset: { line: 1, column: 0 }, + // map: { sources, sourcesContent } + + const map = item.map; + + if (checkSourcesContent(map)) { + hasSourceContent = true; + return; + } + + const done = resolveSourcesContent(map, url); + if (done) { + hasSourceContent = true; + } + + }); + + if (hasSourceContent) { + return flattenSourceMaps(data); + } +}; + +const resolveSourceMap = (data, url) => { + if (!data) { + return; + } + const { + sections, sources, mappings + } = data; + + if (sections) { + return resolveSectionedSourceMap(data, url, sections); + } + + if (!sources || !mappings) { + return; + } + + // check sources content + if (checkSourcesContent(data)) { + return data; + } + + // load sources content by sources + return resolveSourcesContent(data, url); + +}; + +const getInlineSourceMap = (content) => { + let smc; + try { + smc = convertSourceMap.fromSource(content); + } catch (e) { + // ignore "//# sourceMappingURL=" in a string + // console.log(e); + } + return smc; +}; + +const collectSourceMaps = async (v8list, options) => { + + const sourceList = []; + const sourcemapList = []; + const concurrency = new Concurrency(); + for (const item of v8list) { + + const { + type, url, id, source, sourceMap + } = item; + + // source and sourceMap will be saved as separated file (could be cached) + // just keep functions coverage ( could be multiple times, will be merged ) + // so remove source and sourceMap + delete item.source; + delete item.sourceMap; + + // source and sourceMap already saved + const { cachePath } = Util.getCacheFileInfo('source', id, options.cacheDir); + if (fs.existsSync(cachePath)) { + continue; + } + + // save source and sourceMap to separated json file + const sourceData = { + id, + url, + source, + sourceMap + }; + + // remove comments if not debug + if (!Util.isDebug()) { + sourceData.source = convertSourceMap.removeComments(source); + } + + // check sourceMap only for js + if (type === 'js' && !sourceData.sourceMap) { + // from inline sync + const smc = getInlineSourceMap(source); + if (smc) { + sourceData.sourceMap = resolveSourceMap(smc.sourcemap, url); + sourcemapList.push({ + url, + inline: true + }); + sourceList.push(sourceData); + continue; + } + // from url async + const sourceMapUrl = getSourceMapUrl(source, item.url); + if (sourceMapUrl) { + concurrency.addItem({ + sourceMapUrl, + sourceData + }); + continue; + } + } + + // no need check sourceMap + sourceList.push(sourceData); + + } + + // from url concurrency + await concurrency.start(async (item) => { + const { sourceMapUrl, sourceData } = item; + const { url } = sourceData; + const data = await loadSourceMap(sourceMapUrl, options); + if (data) { + sourceData.sourceMap = resolveSourceMap(data, url); + sourcemapList.push({ + url, + sourceMapUrl + }); + } + + sourceList.push(sourceData); + + }); + + return { + sourceList, + sourcemapList + }; + +}; + +module.exports = { + collectSourceMaps, + resolveSourceMap +}; diff --git a/node_modules/monocart-coverage-reports/lib/converter/converter.js b/node_modules/monocart-coverage-reports/lib/converter/converter.js new file mode 100644 index 0000000..44eb155 --- /dev/null +++ b/node_modules/monocart-coverage-reports/lib/converter/converter.js @@ -0,0 +1,1823 @@ +/** + * V8 Coverage Data Converter + * @copyright https://github.com/cenfun/monocart-coverage-reports + * @author cenfun@gmail.com + */ + +const EC = require('eight-colors'); + +const { Locator } = require('monocart-locator'); +const Util = require('../utils/util.js'); + +const findOriginalRange = require('./find-original-range.js'); +const { getJsAstInfo, getCssAstInfo } = require('./ast.js'); +const { getIgnoredRanges } = require('./ignore.js'); + +const { getUntestedList } = require('./untested.js'); + +const { + sortRanges, dedupeCountRanges, mergeRangesWith +} = require('../utils/dedupe.js'); +const { getSourceType, initSourceMapSourcesPath } = require('../utils/source-path.js'); + +const { decode } = require('../packages/monocart-coverage-vendor.js'); + +const InfoBranch = require('./info-branch.js'); +const InfoFunction = require('./info-function.js'); +const InfoStatement = require('./info-statement.js'); + +// ======================================================================================================== + +// debug info +const logMappingErrors = (type, result) => { + + // const { + // errors, start, end, sourcePath + // } = result; + // // if (!sourcePath.endsWith('monocart-v8.js') || type !== 'byte') { + // // return; + // // } + // const list = [ + // Util.EC.red('[Mapping]'), + // Util.EC.magenta(type), + // errors.join(' -> '), + // Util.EC.blue(`${start} ~ ${end}`), + // sourcePath + // ]; + // console.log(list.join(' ')); + +}; + +// ======================================================================================================== + +const handleIgnoredRanges = (list, ignoredRanges) => { + list.forEach((item) => { + const range = Util.findInRanges(item.start, item.end, ignoredRanges); + if (range) { + // console.log(item, range); + item.ignored = true; + } + }); +}; + + +const applyBytesToLines = (bytes, locator, lineMap) => { + bytes.forEach((range) => { + const { + start, end, count, ignored + } = range; + + // no need handle ignored byte + if (ignored) { + return; + } + + const sLoc = locator.offsetToLocation(start); + const eLoc = locator.offsetToLocation(end); + + // update lines coverage + const lines = Util.getRangeLines(sLoc, eLoc); + Util.updateLinesCoverage(lines, count, lineMap); + + }); + + // no ignore items + lineMap.forEach((lineItem, line) => { + + const { + uncoveredEntire, uncoveredPieces, coveredCount + } = lineItem; + + // default count to 1, both js and css + let count = 1; + // full covered true/false for entire line + let covered = true; + + if (uncoveredEntire) { + count = 0; + covered = false; + } else { + count = coveredCount; + const uncoveredLen = uncoveredPieces.length; + if (uncoveredLen > 0) { + covered = false; + // uncovered + count = `1/${uncoveredLen + 1}`; + } + } + + lineItem.covered = covered; + lineItem.count = count; + + }); + +}; + +const handleLinesCoverage = (bytes, locator, ignoredRanges) => { + + // init lines + let blankCount = 0; + let commentCount = 0; + const dataExtras = {}; + // line 1 based + const lineMap = new Map(); + locator.lines.forEach((lineItem) => { + // line 1-base + const line = lineItem.line + 1; + + // exclude blank and comment + if (lineItem.blank) { + blankCount += 1; + dataExtras[line] = 'b'; + return; + } + if (lineItem.comment) { + commentCount += 1; + dataExtras[line] = 'c'; + return; + } + const ignored = Util.findInRanges(lineItem.start, lineItem.end, ignoredRanges); + if (ignored) { + dataExtras[line] = 'i'; + return; + } + + Util.initLineCoverage(lineItem); + + lineMap.set(line, lineItem); + }); + + applyBytesToLines(bytes, locator, lineMap); + + const summaryLines = { + total: 0, + covered: 0, + blank: blankCount, + comment: commentCount + }; + // data lines + const dataLines = {}; + + // no ignore items + lineMap.forEach((lineItem, line) => { + const { count, covered } = lineItem; + // data lines + dataLines[line] = count; + + summaryLines.total += 1; + if (covered) { + summaryLines.covered += 1; + } + }); + + return { + dataLines, + dataExtras, + summaryLines + }; +}; + +// ======================================================================================================== + +const calculateV8Summary = (list) => { + + const summary = { + total: 0, + covered: 0 + }; + + list.forEach((item) => { + if (item.ignored) { + return; + } + + summary.total += 1; + if (item.count > 0) { + summary.covered += 1; + } + }); + + return summary; +}; + +// ======================================================================================================== +// istanbul coverage format +// https://github.com/istanbuljs/istanbuljs/blob/master/docs/raw-output.md +/** + * * `path` - the file path for which coverage is being tracked + * * `statementMap` - map of statement locations keyed by statement index + * * `fnMap` - map of function metadata keyed by function index + * * `branchMap` - map of branch metadata keyed by branch index + * * `s` - hit counts for statements + * * `f` - hit count for functions + * * `b` - hit count for branches + */ +const collectFileCoverage = (v8Data, state, options) => { + + const { + bytes, + functions, + branches, + statements, + + sourcePath, + locator + } = state; + + // ========================================== + // v8 data + const data = { + bytes: dedupeCountRanges(bytes), + functions: [], + branches: [], + statements: [] + }; + + // ========================================== + // ignore + const ignoredRanges = getIgnoredRanges(locator, options); + if (ignoredRanges) { + + data.ignores = ignoredRanges; + + // data bytes is start/end/count object + handleIgnoredRanges(data.bytes, ignoredRanges); + + // functions start/end/count instance + handleIgnoredRanges(functions, ignoredRanges); + + // branches start/end/count instance + handleIgnoredRanges(branches, ignoredRanges); + + // branch locations start/end/count object + branches.forEach((group) => { + if (group.ignored) { + // all branch group ignored + group.locations.forEach((it) => { + it.ignored = true; + }); + } else { + handleIgnoredRanges(group.locations, ignoredRanges); + } + }); + + // statements start/end/count instance + handleIgnoredRanges(statements, ignoredRanges); + + // console.log(ignoredRanges); + + } + + // ========================================== + // lines + // after bytes with ignored, before calculateV8Lines + const { + dataLines, dataExtras, summaryLines + } = handleLinesCoverage(data.bytes, locator, ignoredRanges); + + data.lines = dataLines; + data.extras = dataExtras; + + // console.log('statements', state.sourcePath, statements.length); + + // ========================================== + + data.functions = functions.map((info, i) => { + return info.getRange(i); + }); + sortRanges(data.functions); + + // branch group with locations to flat branches + data.branches = branches.map((info) => { + return info.getRanges(); + }).flat(); + sortRanges(data.branches); + + data.statements = statements.map((info) => { + return info.getRange(); + }); + sortRanges(data.statements); + + // ========================================== + + const summary = { + functions: calculateV8Summary(data.functions), + branches: calculateV8Summary(data.branches), + statements: calculateV8Summary(data.statements), + lines: summaryLines + }; + + // ========================================== + // v8 data and summary + v8Data.data = data; + v8Data.summary = summary; + + // ========================================== + // istanbul + const istanbulData = { + path: sourcePath, + + statementMap: {}, + fnMap: {}, + branchMap: {}, + + s: {}, + f: {}, + b: {} + }; + + statements.filter((it) => !it.ignored).forEach((statement, index) => { + istanbulData.statementMap[`${index}`] = statement.generate(locator); + istanbulData.s[`${index}`] = statement.count; + }); + + functions.filter((it) => !it.ignored).forEach((fn, index) => { + istanbulData.fnMap[`${index}`] = fn.generate(locator, index); + istanbulData.f[`${index}`] = fn.count; + }); + + branches.filter((it) => !it.ignored).forEach((branch, index) => { + const { map, counts } = branch.generate(locator); + istanbulData.branchMap[`${index}`] = map; + istanbulData.b[`${index}`] = counts; + }); + + return istanbulData; + +}; + +// ======================================================================================================== + +const addJsBytesCoverage = (state, range) => { + const { + startOffset, endOffset, count + } = range; + // add bytes range + const byte = { + start: startOffset, + // the end could be > source.length + end: Math.min(endOffset, state.maxContentLength), + count + }; + // for debug + if (Util.isDebug() && state.original) { + byte.generatedStart = range.generatedStart; + byte.generatedEnd = range.generatedEnd; + } + state.bytes.push(byte); +}; + +const addCssBytesCoverage = (state, range) => { + const { + start, end, count + } = range; + // add css bytes range, already start, end + state.bytes.push({ + start, + end, + count + }); +}; + +// ======================================================================================================== + +const checkOriginalRangeCode = (range, state, startEndMap, type) => { + + // only for original + if (!state.original) { + return true; + } + + const { start, end } = range; + if (start >= end) { + // console.log('invalid branch', state.sourcePath, range); + return false; + } + + // could be vue code + const text = state.locator.getSlice(start, end).trim(); + if (!text) { + return false; + } + + // do not check text for `bytes` + // it could be `} ` uncovered in `try { } catch` + // instead, use `dedupeCountRanges` to accumulate count + if (type === 'bytes') { + return true; + } + + // invalid original code + // Matches any character that is not a word character from the basic Latin alphabet. + // Equivalent to [^A-Za-z0-9_] + if (text.length === 1 && (/\W/).test(text)) { + // ; } = + // console.log(text, type, state.sourcePath, range); + return false; + } + + // type: bytes, functions, branches, statements + + // check repeated range + const key = `${start}_${end}`; + if (startEndMap.has(key)) { + return false; + } + startEndMap.set(key, range); + + return true; +}; + +const handleFunctionsCoverage = (state) => { + + // functions only for js + if (!state.js) { + return; + } + + const startEndMap = new Map(); + const { functions, astInfo } = state; + astInfo.functions.forEach((it) => { + + if (!checkOriginalRangeCode(it, state, startEndMap, 'functions')) { + return; + } + + functions.push(new InfoFunction(it, state.original)); + }); + +}; + +const handleBranchesCoverage = (state) => { + + // functions only for js + if (!state.js) { + return; + } + + const startEndMap = new Map(); + const { branches, astInfo } = state; + astInfo.branches.forEach((it) => { + + if (!checkOriginalRangeCode(it, state, startEndMap, 'branches')) { + return; + } + + branches.push(new InfoBranch(it, state.original)); + }); + +}; + +const handleStatementsCoverage = (state) => { + + // statement only for js + if (!state.js) { + return; + } + + const startEndMap = new Map(); + const { statements, astInfo } = state; + astInfo.statements.forEach((it) => { + + if (!checkOriginalRangeCode(it, state, startEndMap, 'statements')) { + return; + } + + statements.push(new InfoStatement(it, state.original)); + }); + +}; + +const handleOriginalBytesCoverage = (state) => { + const startEndMap = new Map(); + state.bytes = state.bytes.filter((it) => { + return checkOriginalRangeCode(it, state, startEndMap, 'bytes'); + }); +}; + +const handleGeneratedBytesCoverage = (state) => { + + // it could be a dist file, do not handle twice + if (state.addedGeneratedBytes) { + return; + } + + const { js, coverageList } = state; + + if (js) { + coverageList.forEach((block) => { + block.ranges.forEach((range) => { + + const { fixedStart, fixedEnd } = Util.fixSourceRange(state.locator, range.startOffset, range.endOffset); + range.startOffset = fixedStart; + range.endOffset = fixedEnd; + + addJsBytesCoverage(state, range); + }); + }); + } else { + coverageList.forEach((range) => { + addCssBytesCoverage(state, range); + }); + } + + state.addedGeneratedBytes = true; + +}; + +// ======================================================================================================== + +const handleOriginalFunctionsCoverage = (state, originalStateMap) => { + + // functions only for js + if (!state.js) { + return; + } + + // console.log(state.astInfo.functions); + + const updateFunctionBodyRange = (start, end, bodyStart, bodyEnd, originalFunction) => { + if (bodyStart !== start || bodyEnd !== end) { + const result = findOriginalRange(bodyStart, bodyEnd, state, originalStateMap); + if (result.error) { + logMappingErrors('function body', result); + } else { + originalFunction.bodyStart = result.start; + originalFunction.bodyEnd = result.end; + } + } + }; + + // function count + state.astInfo.functions.forEach((it) => { + + // remove webpack wrap functions for functions count, not for ranges here + if (it.generatedOnly) { + return; + } + + const { + start, end, bodyStart, bodyEnd + } = it; + + const result = findOriginalRange(start, end, state, originalStateMap, { + checkName: true + }); + if (result.error) { + logMappingErrors('function', result); + return; + } + + const originalFunction = { + ... it, + generatedStart: start, + generatedEnd: end, + start: result.start, + end: result.end, + bodyStart: result.start, + bodyEnd: result.end + }; + + if (result.name) { + originalFunction.functionName = result.name; + } + + // body start and end + updateFunctionBodyRange(start, end, bodyStart, bodyEnd, originalFunction); + + // add back to original ast + result.originalState.astInfo.functions.push(originalFunction); + + }); + +}; + +const handleOriginalBranchesCoverage = (state, originalStateMap) => { + + // branches only for js + if (!state.js) { + return; + } + + // console.log(state.astInfo.branches); + + // function count + state.astInfo.branches.forEach((group) => { + + if (group.generatedOnly) { + return; + } + + const { type, locations } = group; + + // start + const result = findOriginalRange(group.start, group.end, state, originalStateMap); + if (result.error) { + logMappingErrors('branch group', result); + return; + } + + // new group start and end + const groupStart = result.start; + const groupEnd = result.end; + + let hasError; + const newLocations = locations.map((oLoc) => { + + const newLoc = { + ... oLoc + }; + + if (newLoc.none) { + newLoc.start = groupStart; + newLoc.end = groupEnd; + return newLoc; + } + + const locResult = findOriginalRange(newLoc.start, newLoc.end, state, originalStateMap); + if (locResult.error) { + // It should not happen unless it is minify files, the SourceMap has some order problems + logMappingErrors('branch', locResult); + hasError = true; + return newLoc; + } + + // before new range + newLoc.generatedStart = newLoc.start; + newLoc.generatedEnd = newLoc.end; + // mapping to new range + newLoc.start = locResult.start; + newLoc.end = locResult.end; + + return newLoc; + }); + + // ignored group when found error + if (hasError) { + return; + } + + // add back to original ast + result.originalState.astInfo.branches.push({ + type, + start: groupStart, + end: groupEnd, + locations: newLocations + }); + + }); + +}; + +const handleOriginalStatementsCoverage = (state, originalStateMap) => { + + // statements only for js + if (!state.js) { + return; + } + + // statement count + state.astInfo.statements.forEach((it) => { + + if (it.generatedOnly) { + return; + } + + const { start, end } = it; + + const result = findOriginalRange(start, end, state, originalStateMap); + if (result.error) { + logMappingErrors('statement', result); + return; + } + + // add back to original ast + result.originalState.astInfo.statements.push({ + ... it, + generatedStart: start, + generatedEnd: end, + start: result.start, + end: result.end + }); + + }); + + originalStateMap.forEach((originalState) => { + const statements = originalState.astInfo.statements; + if (Util.isList(statements)) { + return; + } + // fake source nothing matched + statements.push({ + start: 0, + end: originalState.source.length, + count: 1 + }); + + }); + +}; + +// ======================================================================================================== + +const handleOriginalEmptyBytesCoverage = (state, originalStateMap) => { + const checkList = []; + + // check original bytes if fully in a wrapper range + originalStateMap.forEach((originalState) => { + const bytes = originalState.bytes; + if (Util.isList(bytes)) { + return; + } + + const { decodedMappings } = originalState; + const len = decodedMappings.length; + if (len < 2) { + return; + } + // sort by original line/column + const startMapping = decodedMappings[0]; + const endMapping = decodedMappings[len - 1]; + // console.log(startMapping, endMapping); + const startOffset = startMapping.generatedOffset; + + if (!endMapping.generatedEndOffset) { + // line last one + const line = state.locator.getLine(endMapping.generatedLine + 1); + // could be no line found + if (line) { + // last column + endMapping.generatedEndOffset = line.end; + } else { + endMapping.generatedEndOffset = endMapping.generatedOffset; + } + } + const endOffset = endMapping.generatedEndOffset; + + // console.log('===========================================================', originalState.sourcePath); + // console.log(originalState.source.length, endMapping); + + checkList.push({ + originalState, + startOffset, + endOffset + }); + + }); + + // no file to handle + if (!checkList.length) { + return; + } + + // there is no state.bytes if not in debug + // should using coverageList to generate bytes first + handleGeneratedBytesCoverage(state); + + checkList.forEach((it) => { + + const { + originalState, startOffset, endOffset + } = it; + + // console.log('=============', 'no bytes', originalState.sourcePath); + + // only check uncovered range + // because a uncovered range could be in a covered wrapper + // { start: 0, end: 12137, count: 1 }, could be { start: > 0, end: < 12137, count: 0 } + for (const range of state.bytes) { + if (range.count > 0) { + continue; + } + if (startOffset >= range.start && endOffset <= range.end) { + // console.log('------------', 'added'); + originalState.bytes.push({ + start: 0, + end: originalState.source.length, + count: 0 + }); + break; + } + } + + }); +}; + + +const handleAllOriginalBytesCoverage = (state, originalStateMap) => { + + const { js, coverageList } = state; + + // only for js, no sourcemap for css for now + if (!js) { + return; + } + + // v8 coverage + coverageList.forEach((block) => { + block.ranges.forEach((range) => { + + // remove wrap functions for original files + if (range.generatedOnly) { + return; + } + + const { + startOffset, endOffset, count + } = range; + + const result = findOriginalRange(startOffset, endOffset, state, originalStateMap, { + fixOriginalRange: true + }); + if (result.error) { + logMappingErrors('byte', result); + return; + } + + addJsBytesCoverage(result.originalState, { + generatedStart: startOffset, + generatedEnd: endOffset, + startOffset: result.start, + endOffset: result.end, + count + }); + + }); + }); + + handleOriginalEmptyBytesCoverage(state, originalStateMap); + +}; + +// ======================================================================================================== + +const decodeSourceMappings = (state, originalDecodedMap) => { + + const generatedLocator = state.locator; + + const { + sources, mappings, decodedMappings + } = state.sourceMap; + + const decodedList = decodedMappings || decode(mappings); + + // console.log(decodedList); + + sources.forEach((source, i) => { + originalDecodedMap.set(i, []); + }); + + const allDecodedMappings = []; + decodedList.forEach((segments, generatedLine) => { + + if (!segments.length) { + return; + } + + // line segments + const lastIndex = segments.length - 1; + segments.forEach((segment, i) => { + + // const COLUMN = 0; + // const SOURCES_INDEX = 1; + // const SOURCE_LINE = 2; + // const SOURCE_COLUMN = 3; + // const NAMES_INDEX = 4; + const [generatedColumn, sourceIndex, originalLine, originalColumn, nameIndex] = segment; + // the segment length could be 1, 4 or 5 + + if (typeof sourceIndex === 'undefined') { + // console.log('============================ sourceIndex undefined'); + // console.log(segment); + return; + } + + // 1-base + const generatedSN = generatedLine + 1; + + const generatedOffset = generatedLocator.locationToOffset({ + // 1-base + line: generatedSN, + column: generatedColumn + }); + + const info = { + generatedOffset, + generatedLine, + generatedColumn, + + sourceIndex, + originalLine, + originalColumn, + nameIndex + }; + + // first and last column + if (i === 0) { + info.first = true; + } + if (i === lastIndex) { + info.last = true; + } + + allDecodedMappings.push(info); + originalDecodedMap.get(sourceIndex).push(info); + + // calculate line end column + if (!info.last) { + return; + } + + const lineItem = generatedLocator.getLine(generatedSN); + if (!lineItem) { + // console.log('============================== not found line item'); + return; + } + + // console.log(generatedSN, generatedColumn, lineItem.length, lineItem.text); + + if (generatedColumn >= lineItem.length) { + return; + } + + const endColumn = { + generatedOffset: generatedOffset + (lineItem.length - generatedColumn), + generatedLine, + generatedColumn: lineItem.length, + + end: true, + + sourceIndex, + originalLine, + originalColumn, + nameIndex + }; + + // console.log(generatedSN, generatedColumn, info, endColumn); + + allDecodedMappings.push(endColumn); + originalDecodedMap.get(sourceIndex).push(endColumn); + + }); + + + }); + + // defaults to sort by generated offset, no need sort + // allDecodedMappings.sort((a, b) => { + // return a.generatedOffset - b.generatedOffset; + // }); + + return allDecodedMappings; +}; + +const getOriginalDecodedMappings = (originalDecodedMap, sourceIndex, locator) => { + // all mappings for the original file sorted + const decodedMappings = originalDecodedMap.get(sourceIndex); + + if (!decodedMappings) { + return []; + } + + // calculate line end column + decodedMappings.forEach((item) => { + if (!item.end) { + return; + } + const originalSN = item.originalLine + 1; + const lineItem = locator.getLine(originalSN); + // console.log(originalSN, item.originalColumn, lineItem.length, lineItem.text); + if (lineItem) { + item.originalColumn = lineItem.length; + } + }); + + // sort by original line/column + decodedMappings.sort((a, b) => { + if (a.originalLine === b.originalLine) { + return a.originalColumn - b.originalColumn; + } + return a.originalLine - b.originalLine; + }); + + // add offset and index + decodedMappings.forEach((item, i) => { + item.originalOffset = locator.locationToOffset({ + line: item.originalLine + 1, + column: item.originalColumn + }); + }); + + return decodedMappings; +}; + +// ======================================================================================================== + +const initOriginalList = (state, originalDecodedMap, options) => { + + // source filter + const sourceFilter = Util.getSourceFilter(options); + + // create original content mappings + const originalStateMap = new Map(); + + const { sources, sourcesContent } = state.sourceMap; + + const lengthBefore = sources.length; + let lengthAfter = 0; + + sources.forEach((sourcePath, sourceIndex) => { + + // filter + // do not change for sourceIndex + if (!sourceFilter(sourcePath)) { + // console.log('-', sourcePath); + return; + } + // console.log(sourcePath); + + // console.log(`add source: ${k}`); + const sourceContent = sourcesContent?.[sourceIndex]; + if (typeof sourceContent !== 'string') { + Util.logError(`not found source content: ${sourcePath}`); + return; + } + + const locator = new Locator(sourceContent); + const maxContentLength = sourceContent.length; + + const decodedMappings = getOriginalDecodedMappings(originalDecodedMap, sourceIndex, locator); + + // unpacked file always is js + + const type = getSourceType(sourcePath); + + const originalState = { + original: true, + // original file is js + js: true, + type, + source: sourceContent, + sourcePath, + locator, + maxContentLength, + decodedMappings, + // coverage info + bytes: [], + functions: [], + branches: [], + statements: [], + astInfo: { + functions: [], + branches: [], + statements: [] + }, + // coverage data + v8Data: {} + }; + + originalStateMap.set(sourceIndex, originalState); + lengthAfter += 1; + }); + + Util.logFilter(`source filter (${state.sourcePath}):`, lengthBefore, lengthAfter); + + return originalStateMap; +}; + +const collectOriginalList = (state, originalStateMap) => { + + const { fileUrls } = state; + const distFile = state.sourcePath; + + let added = 0; + + // collect original files + originalStateMap.forEach((originalState) => { + + const { + js, type, sourcePath, source + } = originalState; + + // add file item + const url = fileUrls[sourcePath] || sourcePath; + + // add dist for id + const id = Util.calculateSha1(sourcePath + source); + + const sourceItem = { + url, + id, + js, + type, + sourcePath, + distFile, + source + }; + + // save v8 data and add to originalList + originalState.v8Data = sourceItem; + state.originalList.push(originalState); + added += 1; + }); + + Util.logDebug(`added source files: ${EC.yellow(added)}`); + +}; + +// ======================================================================================================== + +const generateCoverageForDist = (state) => { + + handleFunctionsCoverage(state); + handleBranchesCoverage(state); + handleStatementsCoverage(state); + handleGeneratedBytesCoverage(state); + +}; + +const handleUncoveredInCovered = (state, originalStateMap) => { + if (!state.fake) { + return; + } + + // fake statements/branches/functions + originalStateMap.forEach((originalState) => { + const { bytes } = originalState; + const list = []; + originalState.bytes = bytes.filter((item) => { + if (item.count === 0) { + const range = bytes.find((it) => { + if (it.count === 0) { + return false; + } + if (it.start > item.end) { + return false; + } + if (it.end < item.start) { + return false; + } + return true; + }); + if (range) { + list.push(item); + return false; + } + } + return true; + }); + + if (!list.length) { + return; + } + + list.forEach((item) => { + ['statements', 'branches', 'functions'].forEach((key) => { + originalState[key] = originalState[key].filter((it) => { + if (it.start === item.start && it.end === item.end) { + return false; + } + return true; + }); + }); + }); + + }); + +}; + +const unpackSourceMap = (state, options) => { + + const { sourceMap, sourcePath } = state; + + // keep original urls + const fileUrls = {}; + initSourceMapSourcesPath(fileUrls, sourceMap, sourcePath, options); + state.fileUrls = fileUrls; + // for function names + state.sourceMapNames = sourceMap.names || []; + + // =============================================== + // decode mappings for each original file + + const originalDecodedMap = new Map(); + // for find-original-range + state.decodedMappings = decodeSourceMappings(state, originalDecodedMap); + + // filter original list and init list + const originalStateMap = initOriginalList(state, originalDecodedMap, options); + + originalDecodedMap.clear(); + + // =============================================== + + // handle functions before handle original state functions + handleOriginalFunctionsCoverage(state, originalStateMap); + handleOriginalBranchesCoverage(state, originalStateMap); + handleOriginalStatementsCoverage(state, originalStateMap); + + // handle lines info before handle ranges to update line count + originalStateMap.forEach((originalState) => { + + handleFunctionsCoverage(originalState); + handleBranchesCoverage(originalState); + handleStatementsCoverage(originalState); + + // if (originalState.sourcePath.endsWith('demo.js')) { + // console.log('=================================', originalState.sourcePath); + // } + + }); + + // handle bytes ranges + handleAllOriginalBytesCoverage(state, originalStateMap); + + originalStateMap.forEach((originalState) => { + handleOriginalBytesCoverage(originalState); + }); + + // remove uncovered in covered for fake + handleUncoveredInCovered(state, originalStateMap); + + // collect coverage for original list + collectOriginalList(state, originalStateMap); + +}; + +const unpackDistFile = (item, state, options) => { + + if (state.sourceMap) { + if (Util.isDebug()) { + // js self + item.debug = true; + generateCoverageForDist(state); + } else { + item.dedupe = true; + } + + // unpack source map + unpackSourceMap(state, options); + + } else { + + // css/js self + generateCoverageForDist(state); + + } + +}; + +// ======================================================================================================== + +const filterCoverageList = (item) => { + const { + functions, scriptOffset, source + } = item; + + // no script offset + if (!scriptOffset) { + return functions; + } + + // vm script offset + const minOffset = scriptOffset; + // the inline sourcemap could be removed + const maxOffset = source.length; + + const wrapperList = []; + + const coverageList = functions.filter((block) => { + + const { ranges } = block; + + // first one is function coverage info + const functionRange = ranges[0]; + const { startOffset, endOffset } = functionRange; + if (startOffset >= minOffset && endOffset <= maxOffset) { + return true; + } + + wrapperList.push(block); + + return false; + }); + + if (wrapperList.length) { + const rootBlock = wrapperList.pop(); + rootBlock.root = true; + coverageList.unshift(rootBlock); + } + + // if (item.sourcePath.includes('PlaceB.tsx')) { + // console.log(coverageList); + // } + + return coverageList; +}; + +const initJsCoverageList = (item) => { + const coverageList = filterCoverageList(item); + + // if (item.sourcePath.includes('PlaceB.tsx')) { + // console.log(coverageList[0]); + // } + + // function could be covered even it is defined after an uncovered return, see case closures.js + // fix uncovered range if there are covered ranges in uncovered range + + const uncoveredBlocks = []; + const uncoveredList = []; + coverageList.forEach((block) => { + block.ranges.forEach((range, i) => { + const { + count, startOffset, endOffset + } = range; + + if (i === 0) { + // check only first level + if (count > 0) { + const inUncoveredRange = Util.findInRanges(startOffset, endOffset, uncoveredBlocks, 'startOffset', 'endOffset'); + if (inUncoveredRange) { + if (!inUncoveredRange.coveredList) { + inUncoveredRange.coveredList = []; + uncoveredList.push(inUncoveredRange); + } + inUncoveredRange.coveredList.push(range); + } + } + return; + } + + if (count === 0) { + uncoveredBlocks.push({ + ... range, + index: i, + ranges: block.ranges + }); + } + + }); + }); + + if (uncoveredList.length) { + + uncoveredList.forEach((it) => { + const { + ranges, index, count, coveredList + } = it; + + // remove previous range first + const args = [index, 1]; + + Util.sortOffsetRanges(coveredList); + let startOffset = it.startOffset; + coveredList.forEach((cov) => { + // ignore sub functions in the function + if (cov.startOffset > startOffset) { + args.push({ + startOffset, + endOffset: cov.startOffset, + count + }); + startOffset = cov.endOffset; + } + }); + + if (it.endOffset > startOffset) { + args.push({ + startOffset, + endOffset: it.endOffset, + count + }); + } + + ranges.splice(... args); + + }); + } + + return coverageList; +}; + +const logConvertTime = (msg, time_start, untested) => { + if (untested) { + return; + } + Util.logTime(msg, time_start); +}; + +const convertCoverages = (list, options, untested) => { + const stateList = []; + + for (const item of list) { + // console.log([item.id]); + + const time_start_ast = Date.now(); + + const { + type, source, fake, sourcePath + } = item; + + // for source file, type could be ts or vue as extname, but js = true + const js = type === 'js'; + item.js = js; + + // source mapping + const locator = new Locator(source); + const maxContentLength = source.length; + + // ============================ + // move sourceMap + const sourceMap = item.sourceMap; + if (sourceMap) { + delete item.sourceMap; + } + + // ============================ + // move functions and ranges to coverageList + let coverageList = []; + let astInfo; + if (js) { + coverageList = initJsCoverageList(item); + // remove original functions + if (!Util.isDebug()) { + delete item.functions; + } + astInfo = getJsAstInfo(item, coverageList); + } else { + // convent css covered ranges to rules ranges and include uncovered ranges + astInfo = getCssAstInfo(item, coverageList); + // remove original ranges + if (!Util.isDebug()) { + delete item.ranges; + } + } + + logConvertTime(`${EC.magenta('│ ')}${EC.cyan('├')} [convert] parsed ast: ${sourcePath} (${EC.cyan(Util.BSF(maxContentLength))})`, time_start_ast, untested); + + // console.log(sourcePath, astInfo.statements.length); + // ============================ + + const time_start_unpack = Date.now(); + + // current file and it's sources from sourceMap + // see const originalState + const state = { + js, + type, + source, + fake, + sourcePath, + sourceMap, + locator, + maxContentLength, + decodedMappings: [], + rangeCache: new Map(), + diffCache: new Map(), + + // alignTextList: [], + + // coverage info + bytes: [], + functions: [], + branches: [], + statements: [], + astInfo, + // for sub source files + coverageList, + originalList: [], + // coverage data + v8Data: item + }; + + unpackDistFile(item, state, options); + const unpackedFiles = EC.cyan(`${state.originalList.length} files`); + + stateList.push(state); + + logConvertTime(`${EC.magenta('│ ')}${EC.cyan('├')} [convert] unpacked sourcemap: ${sourcePath} (${unpackedFiles})`, time_start_unpack, untested); + + } + + return stateList; +}; + +// ======================================================================================================== + +const isUncoveredRange = (range, key, uncoveredGroups) => { + + let uncovered = true; + uncoveredGroups.forEach((group) => { + const { groupMap, state } = group; + + // ======================================================== + // self key + if (groupMap.has(key)) { + return; + } + + // ======================================================== + // in all group + for (const item of groupMap.values()) { + if (range.start >= item.start && range.end <= item.end) { + return; + } + } + + // ======================================================== + // no sourcemap mappings in range + // check original range in decodedMappings + const { decodedMappings } = state; + const item = decodedMappings.find((it) => it.originalOffset >= range.start && it.originalOffset <= range.end); + if (!item) { + return; + } + + // ======================================================== + uncovered = false; + + }); + + return uncovered; + +}; + +const mergeV8Data = (state, stateList) => { + // console.log(stateList); + + // let debug = false; + // if (state.sourcePath.endsWith('counter')) { + // debug = true; + // console.log('merge v8 data ===================================', state.sourcePath); + // console.log('bytes before ============', stateList.map((it) => it.bytes)); + // // console.log('statements ==============', stateList.map((it) => it.statements)); + // // console.log('functions ==============', stateList.map((it) => it.functions)); + // // console.log('branches ======================', stateList.map((it) => it.branches.map((b) => [`${b.start}-${b.end}`, JSON.stringify(b.locations.map((l) => l.count))]))); + // } + + // =========================================================== + // bytes + const mergedBytes = []; + + const coveredMap = new Map(); + const uncoveredMap = new Map(); + const uncoveredGroups = []; + stateList.forEach((st) => { + const groupMap = new Map(); + const bytes = dedupeCountRanges(st.bytes); + bytes.forEach((range) => { + const key = `${range.start}_${range.end}`; + if (range.count) { + mergedBytes.push(range); + coveredMap.set(key, true); + } else { + uncoveredMap.set(key, range); + groupMap.set(key, range); + } + }); + + uncoveredGroups.push({ + groupMap, + state: st + }); + }); + + // if (debug) { + // console.log('coveredMap ============', coveredMap); + // console.log('uncoveredMap ============', uncoveredMap); + // console.log('uncoveredGroups ============', uncoveredGroups); + // } + + uncoveredMap.forEach((range, key) => { + + // in covered range + if (coveredMap.has(key)) { + return; + } + + if (isUncoveredRange(range, key, uncoveredGroups)) { + mergedBytes.push(range); + } + + }); + + // will be dedupeCountRanges in collectFileCoverage + state.bytes = mergedBytes; + + // if (debug) { + // console.log('bytes after ============', mergedBytes); + // } + + // =========================================================== + // functions + const allFunctions = stateList.map((it) => it.functions).flat(); + const functionComparer = (lastRange, range) => { + // if (lastRange.start === range.start && lastRange.end === range.end) { + // return true; + // } + + // function range could be from sourcemap, not exact matched + + // end is same + // {start: 2017, end: 2315, count: 481} + // {start: 2018, end: 2315, count: 14} + + // start is same + // {start: 10204, end: 10379, count: 0} + // {start: 10204, end: 10393, count: 5} + + // only one position matched could be same + if (lastRange.start === range.start || lastRange.end === range.end) { + // console.log(lastRange.start, range.start, lastRange.end, range.end); + + // if (lastRange.start === range.start) { + // console.log(range.end - lastRange.end, lastRange.start, lastRange.end, 'end', range.end, state.sourcePath); + // } else { + // console.log(range.start - lastRange.start, lastRange.start, lastRange.end, 'start', range.start, state.sourcePath); + // } + + return true; + } + + return false; + }; + const functionHandler = (lastRange, range) => { + lastRange.count += range.count; + }; + const mergedFunctions = mergeRangesWith(allFunctions, functionComparer, functionHandler); + state.functions = mergedFunctions; + + // =========================================================== + // statements + const allStatements = stateList.map((it) => it.statements).flat(); + const statementComparer = (lastRange, range) => { + // exact matched because the statement range is generated from ast + return lastRange.start === range.start && lastRange.end === range.end; + }; + const statementHandler = (lastRange, range) => { + // merge statements count + lastRange.count += range.count; + }; + const mergedStatements = mergeRangesWith(allStatements, statementComparer, statementHandler); + state.statements = mergedStatements; + + // =========================================================== + // branches + const allBranches = stateList.map((it) => it.branches).flat(); + const branchComparer = (lastRange, range) => { + // exact matched because the branch range is generated from ast + return lastRange.start === range.start && lastRange.end === range.end; + }; + const branchHandler = (lastRange, range) => { + // merge locations count + lastRange.locations.forEach((item, i) => { + const loc = range.locations[i]; + if (loc) { + item.count += loc.count; + } + }); + }; + const mergedBranches = mergeRangesWith(allBranches, branchComparer, branchHandler); + state.branches = mergedBranches; + + // if (sourcePath.endsWith('scroll_zoom.ts')) { + // console.log(mergedBytes); + // console.log(mergedFunctions); + // console.log(mergedBranches.map((b) => [`${b.start}-${b.end}`, JSON.stringify(b.locations.map((l) => l.count))])); + // } + + +}; + +const addUntestedFiles = async (stateList, options) => { + + const time_start_untested = Date.now(); + + const testedMap = new Map(); + stateList.forEach((state) => { + const { v8Data, originalList } = state; + // dedupe dist file if not debug + if (!v8Data.dedupe) { + testedMap.set(state.sourcePath, true); + } + originalList.forEach((originalState) => { + testedMap.set(originalState.sourcePath, true); + }); + }); + + // console.log('testedMap', testedMap); + + const untestedList = await getUntestedList(testedMap, options, 'v8'); + if (!untestedList) { + return; + } + + const untestedStateList = convertCoverages(untestedList, options, true); + + // console.log(untestedStateList); + untestedStateList.forEach((state) => { + stateList.push(state); + }); + + // console.log('untestedList', untestedList); + + Util.logTime(`${EC.magenta('│ ')}${EC.cyan('├')} [convert] added untested files: ${EC.yellow(untestedList.length)}`, time_start_untested); + + +}; + +const generateV8DataList = (stateList, options) => { + + const stateMap = new Map(); + + // all original files from dist + const allOriginalList = []; + stateList.forEach((state) => { + const { v8Data, originalList } = state; + // dedupe dist file if not debug + if (!v8Data.dedupe) { + stateMap.set(v8Data.id, state); + } + allOriginalList.push(originalList); + }); + + // merge istanbul and v8(converted) + const mergeMap = new Map(); + allOriginalList.flat().forEach((originalState) => { + const { v8Data } = originalState; + const id = v8Data.id; + // exists item + const prevState = stateMap.get(id); + if (prevState) { + // ignore empty item, just override it + if (!prevState.v8Data.empty) { + if (mergeMap.has(id)) { + mergeMap.get(id).push(originalState); + } else { + mergeMap.set(id, [prevState, originalState]); + } + return; + } + } + stateMap.set(id, originalState); + }); + + const mergeIds = mergeMap.keys(); + for (const id of mergeIds) { + const state = stateMap.get(id); + // for source the type could be ts, so just use js (boolean) + if (state.js) { + mergeV8Data(state, mergeMap.get(id)); + } else { + // should no css here, css can not be in sources + } + } + + // new v8 data list (includes sources) + const v8DataList = []; + // global file sources and istanbul coverage data + const fileSources = {}; + const coverageData = {}; + stateMap.forEach((state) => { + const { v8Data } = state; + const istanbulData = collectFileCoverage(v8Data, state, options); + const { sourcePath, source } = v8Data; + v8DataList.push(v8Data); + fileSources[sourcePath] = source; + coverageData[sourcePath] = istanbulData; + }); + + // sort v8DataList (files) + v8DataList.sort((a, b) => { + if (a.sourcePath > b.sourcePath) { + return 1; + } + return -1; + }); + + return { + v8DataList, + fileSources, + coverageData + }; +}; + +const convertV8List = async (v8list, options) => { + + // for tested files + const stateList = convertCoverages(v8list, options); + + // empty coverage handler + await addUntestedFiles(stateList, options); + + const time_start_convert = Date.now(); + const dataList = generateV8DataList(stateList, options); + const dataFiles = EC.cyan(`${dataList.v8DataList.length} files`); + Util.logTime(`${EC.magenta('│ ')}${EC.cyan('├')} [convert] converted data list (${dataFiles})`, time_start_convert); + + return dataList; +}; + +module.exports = { + convertV8List +}; diff --git a/node_modules/monocart-coverage-reports/lib/converter/find-original-range.js b/node_modules/monocart-coverage-reports/lib/converter/find-original-range.js new file mode 100644 index 0000000..a1cf3a5 --- /dev/null +++ b/node_modules/monocart-coverage-reports/lib/converter/find-original-range.js @@ -0,0 +1,980 @@ +const { diffSequence } = require('../packages/monocart-coverage-vendor.js'); +const Util = require('../utils/util.js'); +const EC = Util.EC; + +const findMapping = (list, offset) => { + let start = 0; + let end = list.length - 1; + while (end - start > 1) { + const i = Math.floor((start + end) * 0.5); + const item = list[i]; + if (offset < item.generatedOffset) { + end = i; + continue; + } + if (offset > item.generatedOffset) { + start = i; + continue; + } + return list[i]; + } + // last two items, less is start + const startItem = list[start]; + if (offset === startItem.generatedOffset) { + return startItem; + } + const endItem = list[end]; + if (offset === endItem.generatedOffset) { + return endItem; + } + + // between two mappings + if (offset > startItem.generatedOffset && offset < endItem.generatedOffset) { + return [startItem, endItem]; + } + + // not found the mappings + +}; + +// ======================================================================================================== + +const alignText = (gt, ot, info) => { + + const { diffCache } = info.state; + + if (diffCache.has(gt)) { + const subMap = diffCache.get(gt); + if (subMap.has(ot)) { + return subMap.get(ot); + } + } + + const toList = (s) => { + return s.split('').map((v, i) => { + return { + index: i, + value: v + }; + }); + }; + + const mergeList = (gList, oList) => { + const oLen = oList.length; + if (!oLen) { + return; + } + const gLen = gList.length; + if (gLen === oLen) { + gList.forEach((item, i) => { + item.original = oList[i]; + }); + } + }; + + const gl = toList(gt); + const ol = toList(ot); + + // console.log(gl); + // console.log(ol); + + const commonItems = []; + diffSequence(gl.length, ol.length, (gi, oi) => { + return gl[gi].value === ol[oi].value; + }, (len, gi, oi) => { + commonItems.push([gi, oi, len]); + }); + + // console.log(commonItems); + // console.log('================================================================'); + // merge list + // previous index + let gpi = 0; + let opi = 0; + commonItems.forEach(([gi, oi, len]) => { + + if (gpi !== gi) { + const gList = gl.slice(gpi, gi); + const oList = ol.slice(opi, oi); + mergeList(gList, oList); + } + + for (let i = 0; i < len; i++) { + + const gii = gi + i; + const oii = oi + i; + const gItem = gl[gii]; + gItem.original = ol[oii]; + + // matching a word end + if (i === len - 1 && len > 1) { + gItem.wordEnd = true; + } + + } + gpi = gi + len; + opi = oi + len; + }); + + // console.log(JSON.stringify(data.gt)); + // console.log(JSON.stringify(data.ot)); + if (gpi < gl.length && opi < ol.length) { + const gList = gl.slice(gpi); + const oList = ol.slice(opi); + mergeList(gList, oList); + } + + if (diffCache.has(gt)) { + const subMap = diffCache.get(gt); + subMap.set(ot, gl); + } else { + const subMap = new Map(); + diffCache.set(gt, subMap); + subMap.set(ot, gl); + } + + // console.log(gl); + return gl; +}; + +const getWordEndPosition = (list, gp, direction) => { + // for end only + if (direction !== 'end') { + return; + } + + const prev = list[gp - 1]; + if (prev && prev.original && prev.wordEnd) { + const op = prev.original.index + 1; + // console.log(gp, JSON.stringify(gt)); + // console.log(op, JSON.stringify(ot)); + return { + pos: op + }; + } +}; + +const getAlignPosition = (info, direction) => { + + const gt = info.generatedText; + const gp = info.generatedPos; + const ot = info.originalText; + + // const alignTextItem = { + // gt, ot, gp + // }; + // info.state.alignTextList.push(it); + + // there is no need to align for long text + const maxLength = 100; + if (gt.length > maxLength || ot.length > maxLength) { + // console.log(gt.length, ot.length, gp); + return; + } + + // generatedText: '"false";\n', + // originalText: "'false';\r\n ", + // generatedPos: 7 + + // left matched + + // originalText: '1;', + // generatedText: '1;else', + // generatedLeft: '1;' + + // right matched + // only for original first line text + + // exclusive + const list = alignText(gt, ot, info); + const item = list[gp]; + if (item && item.original) { + + // alignTextItem.op = item.original.index; + + return { + pos: item.original.index + }; + } + + // inclusive, for end only + return getWordEndPosition(list, gp, direction); + +}; + +// ======================================================================================================== + +const getBlockStartPosition = (originalLineText) => { + // originalText: 'argument) {', + // generatedLeft: 'o', + // generatedRight: '&&' + + // function/block could be started with {( + const startBlockIndex = originalLineText.search(/[<{(]/); + if (startBlockIndex !== -1) { + return { + pos: startBlockIndex + }; + } + + // end a block + const list = ['>', '}', ')']; + for (const s of list) { + const endBlockIndex = originalLineText.lastIndexOf(s); + if (endBlockIndex !== -1) { + return { + pos: endBlockIndex + 1 + }; + } + } + + // ============================ + // end characters + + // ends with ">" in vue + // + + // originalText: '">', + // generatedText: ' ? ((0,vue__.openBlock)(), ' + + // originalMethod?.apply + // originalText: '?.' no ? + + const indexEndBlock = originalLineText.search(/(?<=[;,:"'\s])/); + if (indexEndBlock !== -1) { + return { + pos: indexEndBlock + }; + } + +}; + +const getBlockEndPosition = (originalLineText) => { + + // generatedText: 'e),', + // generatedPos: 2, + // originalText: 'prop))' + + // generatedText: ' = false)', + // generatedPos: 8, + // originalText: '=false"' + + // generatedText: '), 1 /* TEXT */)])])) : (0,vue__...)("v-if", true)], 6 /* CLASS, STYLE */);', + // generatedPos: 17, + // originalText: ' }}' + + // end marks + const list = ['>', '}', ')']; + for (const s of list) { + const endBlockIndex = originalLineText.lastIndexOf(s); + if (endBlockIndex !== -1) { + return { + pos: endBlockIndex + 1 + }; + } + } + + const startBlockIndex = originalLineText.search(/[<{(]/); + if (startBlockIndex !== -1) { + return { + pos: startBlockIndex + }; + } + +}; + +// ======================================================================================================== + +const getComparedPosition = (info, direction) => { + + const gt = info.generatedText; + const gp = info.generatedPos; + const ot = info.originalText; + const olt = info.originalLineText; + + // seems direction is start only + if (gp === 0) { + return; + } + + // whole generated text + if (gp >= gt.length) { + // console.log(JSON.stringify(gt), gt.length, gp); + // console.log(JSON.stringify(ot)); + return { + pos: olt.length + }; + } + + // ============================= + // trim + + const gtt = gt.trim(); + // no generated content after trim + if (!gtt) { + return; + } + + const ott = ot.trim(); + // no original content after trim + if (!ott) { + return { + pos: direction === 'start' ? ot.length : 0 + }; + } + + // same content + if (gtt === ott) { + // fix indent + const blankBlock = /\S/; + const gi = gt.search(blankBlock); + const oi = ot.search(blankBlock); + + return { + pos: gp - gi + oi + }; + } + + // ============================= + + return getAlignPosition(info, direction); + +}; + + +const getSimilarPosition = (info, direction) => { + + const originalText = info.originalText; + // never cross line, using first line of original text + // trim end remove \r\n and \n + const originalLines = originalText.split(/\n/); + if (originalLines.length === 1) { + // already single line + info.originalLineText = originalText.trimEnd(); + } else { + // multiple liens + info.originalLineText = originalLines[0].trimEnd(); + } + + // no need comparison for fake source + if (info.state.fake) { + return; + } + + const textPos = getComparedPosition(info, direction); + if (textPos) { + return textPos; + } + + // console.log('===================================================================='); + // console.log(`${EC.magenta(direction)} similar position can NOT be fixed`, info.originalState.sourcePath); + // console.log({ + // direction, + // generatedText: info.generatedText, + // generatedPos: info.generatedPos, + // originalText + // }); + +}; + +const getFixedPosition = (info, direction) => { + + const similarPos = getSimilarPosition(info, direction); + if (similarPos) { + return similarPos.pos; + } + + + // generatedText: never cross lines + // originalText: could be multiple lines + // originalLineText: single line originalText + const { originalLineText } = info; + + if (direction === 'start') { + const blockPos = getBlockStartPosition(originalLineText); + if (blockPos) { + return blockPos.pos; + } + return 0; + } + + const blockPos = getBlockEndPosition(originalLineText); + if (blockPos) { + return blockPos.pos; + } + return originalLineText.length; +}; + +// ======================================================================================================== + +const getOriginalEndOffset = (m, originalState) => { + if (!m.originalEndOffset) { + const line = originalState.locator.getLine(m.originalLine + 1); + m.originalEndOffset = line ? line.end : m.originalOffset; + } + return m.originalEndOffset; +}; + +const getOriginalText = (m1, m2, originalState, startNextLine) => { + const originalLocator = originalState.locator; + + const o1 = m1.originalOffset; + const o2 = m2.originalOffset; + const sameLine = m2.originalLine === m1.originalLine; + + // o1 < o2: most of time + if (o1 < o2) { + + // could be in comments + // it must be wrong sourcemap, do not fix it here + // if (originalLocator.lineParser.commentParser.isComment(o1, o2)) { + // console.log('in comments', originalLocator.getSlice(o1, o2), originalLocator.offsetToLocation(o1), originalLocator.offsetToLocation(o2), cache.originalState.sourcePath); + // return { + // originalOffset: o1, + // originalText: '' + // }; + // } + + if (sameLine) { + return { + originalOffset: o1, + originalText: originalLocator.getSlice(o1, o2) + }; + } + + // start from next line + if (startNextLine) { + const nextLine = originalState.locator.getLine(m1.originalLine + 2); + if (nextLine) { + // console.log(nextLine); + return { + originalOffset: nextLine.start + nextLine.indent, + originalText: nextLine.text.slice(nextLine.indent) + }; + } + } + + // could be multiple lines for original text + return { + originalOffset: o1, + originalText: originalLocator.getSlice(o1, getOriginalEndOffset(m1, originalState)) + }; + } + + // esbuild fixing two mapping have same original + // m1 to end line + if (o1 === o2) { + return { + originalOffset: o1, + originalText: originalLocator.getSlice(o1, getOriginalEndOffset(m1, originalState)) + }; + } + + // o1 > o2: should be wrong sourcemap + + // just reverse offsets if same line + if (sameLine) { + return { + originalOffset: o2, + originalText: originalLocator.getSlice(o2, o1) + }; + } + + // if (direction === 'start') { + // should be m2 ? + // console.log(direction, cache.originalState.sourcePath); + // console.log(m1, m2); + // } + + // should be wrong, ignore m2 + return { + originalOffset: o1, + originalText: originalLocator.getSlice(o1, getOriginalEndOffset(m1, originalState)) + }; + +}; + +const getGeneratedText = (m1, m2, state, offset) => { + const generatedLocator = state.locator; + + const o1 = m1.generatedOffset; + const o2 = m2.generatedOffset; + + // same line + if (m1.generatedLine === m2.generatedLine) { + return { + generatedText: generatedLocator.getSlice(o1, o2), + generatedPos: offset - o1 + }; + } + + // ======================================= + // different lines + // never cross lines + + // 1-base + const lineInfo = generatedLocator.offsetToLocation(offset); + // 0-base + const targetLine = lineInfo.line - 1; + + // m1 p (case 1, right to end) + // p (case 2, mid line) + // p (case 3) m2 + + // case 1 + if (targetLine === m1.generatedLine) { + return { + generatedText: generatedLocator.getSlice(o1, lineInfo.end), + generatedPos: offset - o1 + }; + } + + // case 3 + if (targetLine === m2.generatedLine) { + return { + generatedText: generatedLocator.getSlice(lineInfo.start, o2), + generatedPos: offset - lineInfo.start + }; + } + + // case 2 + return { + generatedText: lineInfo.text, + generatedPos: offset - lineInfo.start + }; + +}; + +// ======================================================================================================== +const getFunctionName = (mp, state, options) => { + if (options.checkName && typeof mp.nameIndex !== 'undefined') { + return state.sourceMapNames[mp.nameIndex]; + } +}; + +const getFixedOriginalStart = (start, mappings, state, cache, options) => { + + const [m1, m2] = mappings; + const { originalState, crossStart } = cache; + + // cross file from start of line + if (crossStart) { + return { + originalStart: m2.originalOffset, + originalName: getFunctionName(m2, state, options) + }; + } + + // skip last and end column mapping + let startNextLine = false; + if (m1.end || m1.last) { + const locStart = state.locator.offsetToLocation(start); + // 1-base + const lineIndex = locStart.line - 1; + if (lineIndex > m1.generatedLine) { + startNextLine = true; + // console.log(originalState.sourcePath, start, m1, m2); + } + } + + const { originalText, originalOffset } = getOriginalText(m1, m2, originalState, startNextLine); + const { generatedText, generatedPos } = getGeneratedText(m1, m2, state, start); + const direction = 'start'; + + const info = { + state, + generatedText, + generatedPos, + originalText, + originalState + }; + + const originalPos = getFixedPosition(info, direction); + + // if (start === 2660) { + // console.log('====================================================='); + // console.log('fixed start', originalState.sourcePath); + // console.log({ + // generatedText, + // generatedPos, + // originalText, + // originalPos + // }); + // } + + return { + originalStart: originalOffset + originalPos, + originalName: getFunctionName(m1, state, options) + }; +}; + +const getFixedOriginalEnd = (end, mappings, state, cache) => { + + const [m1, m2] = mappings; + const { originalState, crossEnd } = cache; + + // cross file until e1 line end (not file end) + if (crossEnd) { + const originalEndOffset = getOriginalEndOffset(m1, originalState); + return { + originalEnd: originalEndOffset + }; + } + + // end is exclusive + // quick check previous one if exact match + // most of case is matching "}" + if (m1.generatedOffset === end - 1) { + return { + originalEnd: m1.originalOffset + 1 + }; + } + + + const { originalText, originalOffset } = getOriginalText(m1, m2, originalState); + const { generatedText, generatedPos } = getGeneratedText(m1, m2, state, end); + const direction = 'end'; + + const info = { + state, + offset: end, + generatedText, + generatedPos, + originalText, + originalState + }; + + const originalPos = getFixedPosition(info, direction); + + // if (end === 1304578) { + // console.log('====================================================='); + // console.log('fixed end', originalState.sourcePath); + // console.log({ + // generatedText, + // generatedPos, + // originalText, + // originalPos, + // originalLineText: info.originalLineText + // }); + // } + + return { + originalEnd: originalOffset + originalPos + }; +}; + +// ======================================================================================================== + +const getOriginalStartPosition = (cache, state, options) => { + + const { start, startMappings } = cache; + + if (Array.isArray(startMappings)) { + return getFixedOriginalStart(start, startMappings, state, cache, options); + } + + // Exact match + return { + originalStart: startMappings.originalOffset, + originalName: getFunctionName(startMappings, state, options) + }; +}; + +const getOriginalExclusiveEnd = (cache, state) => { + // end, exclusive mappings + const { end } = cache; + const { decodedMappings } = state; + const endMappings = findMapping(decodedMappings, end); + if (!endMappings) { + return { + error: true, + errors: ['not found end mappings'] + }; + } + if (Array.isArray(endMappings)) { + return getFixedOriginalEnd(end, endMappings, state, cache); + } + + // Exact match end + return { + originalEnd: endMappings.originalOffset + }; +}; + +const getOriginalEndPosition = (cache, state) => { + + const { endMappings, originalState } = cache; + + // (end - 1), inclusive + if (Array.isArray(endMappings)) { + return getOriginalExclusiveEnd(cache, state); + } + + // Exact match (end - 1) + + // check end char + const oi = endMappings.originalOffset; + const originalEndChar = originalState.locator.getSlice(oi, oi + 1); + // the char should never end with "{" or "(" + if (['{', '('].includes(originalEndChar)) { + return getOriginalExclusiveEnd(cache, state); + } + + // inclusive to exclusive + return { + originalEnd: oi + 1 + }; +}; + +// ======================================================================================================== + +const checkSourceFileIndexes = (startIndexes, endIndexes) => { + + const checkIndex11 = (s1, e1) => { + if (s1 === e1) { + return { + sourceIndex: s1 + }; + } + }; + + const checkIndex21 = (s1, s2, e1) => { + if (s1 === e1 || s2 === e1) { + if (s1 === s2) { + return { + sourceIndex: e1 + }; + } + return { + crossStart: true, + sourceIndex: e1 + }; + } + }; + + const checkIndex12 = (s1, e1, e2) => { + if (s1 === e1 || s1 === e2) { + if (e1 === e2) { + return { + sourceIndex: s1 + }; + } + return { + crossEnd: true, + sourceIndex: s1 + }; + } + }; + + const checkIndex22 = (s1, s2, e1, e2) => { + // 4 same + if (s1 === s2 && e1 === e2 && s1 === e1) { + return { + sourceIndex: s1 + }; + } + + if (e1 === e2) { + return checkIndex21(s1, s2, e1); + } + + if (s1 === s2) { + return checkIndex12(s1, e1, e2); + } + + if (s2 === e1) { + return { + crossStart: true, + crossEnd: true, + sourceIndex: s2 + }; + } + + // both between two mappings: 38,39 ~ 38,39 + // if (s1 === e1 && s2 === e2) { + // } + }; + + // both exact matched + if (startIndexes.length === 1 && endIndexes.length === 1) { + return checkIndex11(startIndexes[0], endIndexes[0]); + } + + if (startIndexes.length === 2 && endIndexes.length === 1) { + return checkIndex21(startIndexes[0], startIndexes[1], endIndexes[0]); + } + + if (startIndexes.length === 1 && endIndexes.length === 2) { + return checkIndex12(startIndexes[0], endIndexes[0], endIndexes[1]); + } + + // both 2 mappings + return checkIndex22(startIndexes[0], startIndexes[1], endIndexes[0], endIndexes[1]); + +}; + +const getOriginalState = (start, end, state, originalMap) => { + + const mappingInfo = getMappingInfo(start, end, state); + if (mappingInfo.error) { + return mappingInfo; + } + + const { startMappings, endMappings } = mappingInfo; + + // check source file indexes + const startIndexes = [].concat(startMappings).map((it) => it.sourceIndex); + const endIndexes = [].concat(endMappings).map((it) => it.sourceIndex); + const results = checkSourceFileIndexes(startIndexes, endIndexes); + if (!results) { + return { + error: true, + errors: [`invalid source indexes: ${EC.yellow(`${startIndexes} ~ ${endIndexes}`)}`] + }; + } + + const { + sourceIndex, crossStart, crossEnd + } = results; + + // if (crossStart || crossEnd) { + // console.log(EC.magenta('cross file'), EC.yellow(`${startIndexes} ~ ${endIndexes}`)); + // } + + const originalState = originalMap.get(sourceIndex); + if (!originalState) { + return { + error: true, + errors: [`not found original file: ${EC.yellow(sourceIndex)}`] + }; + } + + // cache for original info + return { + // for debug + // startIndexes, + // endIndexes, + + start, + end, + startMappings, + endMappings, + + sourceIndex, + crossStart, + crossEnd, + originalState + }; +}; + +const getMappingInfo = (start, end, state) => { + + const { decodedMappings } = state; + // possible no length + if (decodedMappings.length < 2) { + return { + error: true, + errors: ['invalid decoded mappings (length < 2)'] + }; + } + + // start: inclusive + const startMappings = findMapping(decodedMappings, start); + if (!startMappings) { + return { + error: true, + errors: ['not found start mappings'] + }; + } + + // end: exclusive + const endMappings = findMapping(decodedMappings, end - 1); + if (!endMappings) { + return { + error: true, + errors: ['not found end mappings'] + }; + } + + // could be 4 mappings found + return { + startMappings, + endMappings + }; +}; + + +const findOriginalRange = (start, end, state, originalMap, options = {}) => { + + const { sourcePath, rangeCache } = state; + + const key = `${start}_${end}_${Boolean(options.fixOriginalRange)}`; + if (rangeCache.has(key)) { + return rangeCache.get(key); + } + + const createMappingError = (errors) => { + const res = { + error: true, + start, + end, + sourcePath, + errors + }; + + // cache error response + rangeCache.set(key, res); + + return res; + }; + + const cache = getOriginalState(start, end, state, originalMap); + if (cache.error) { + return createMappingError(cache.errors); + } + + const originalStartResult = getOriginalStartPosition(cache, state, options); + const { originalStart, originalName } = originalStartResult; + // could be used for end + cache.originalStart = originalStart; + + const originalEndResult = getOriginalEndPosition(cache, state); + if (originalEndResult.error) { + return createMappingError(originalEndResult.errors); + } + const { originalEnd } = originalEndResult; + + // range start > end + if (originalStart > originalEnd) { + return createMappingError([`invalid original start > end: ${EC.yellow(originalStart)} > ${EC.yellow(originalEnd)}`]); + } + + const { originalState } = cache; + const locator = originalState.locator; + + const inComment = locator.lineParser.commentParser.isComment(originalStart, originalEnd); + if (inComment) { + return createMappingError(['the range in a original comment']); + } + + const res = { + start: originalStart, + end: originalEnd, + name: originalName, + originalState + }; + + if (options.fixOriginalRange) { + const { fixedStart, fixedEnd } = Util.fixSourceRange(locator, originalStart, originalEnd); + res.start = fixedStart; + res.end = fixedEnd; + } + + // cache response + rangeCache.set(key, res); + + return res; + +}; + +module.exports = findOriginalRange; diff --git a/node_modules/monocart-coverage-reports/lib/converter/flatten-source-maps.js b/node_modules/monocart-coverage-reports/lib/converter/flatten-source-maps.js new file mode 100644 index 0000000..0a2b773 --- /dev/null +++ b/node_modules/monocart-coverage-reports/lib/converter/flatten-source-maps.js @@ -0,0 +1,186 @@ +const { decode } = require('../packages/monocart-coverage-vendor.js'); + +const COLUMN = 0; +const SOURCES_INDEX = 1; +const SOURCE_LINE = 2; +const SOURCE_COLUMN = 3; +const NAMES_INDEX = 4; + +function getLine(arr, index) { + for (let i = arr.length; i <= index; i++) { + arr[i] = []; + } + return arr[index]; +} + +function getMapping(seg, column, sourcesOffset, namesOffset) { + + const sourcesIndex = sourcesOffset + seg[SOURCES_INDEX]; + const sourceLine = seg[SOURCE_LINE]; + const sourceColumn = seg[SOURCE_COLUMN]; + + if (seg.length === 4) { + return [column, sourcesIndex, sourceLine, sourceColumn]; + } + + return [column, sourcesIndex, sourceLine, sourceColumn, namesOffset + seg[NAMES_INDEX]]; +} + +function addMappings(options, sourcesOffset, namesOffset) { + + const { + input, + lineOffset, + columnOffset, + stopLine, + stopColumn + } = options; + + const decoded = decode(input.mappings); + + for (let i = 0; i < decoded.length; i++) { + const lineI = lineOffset + i; + + if (lineI > stopLine) { + return; + } + + const out = getLine(options.decodedMappings, lineI); + const cOffset = i === 0 ? columnOffset : 0; + + const line = decoded[i]; + for (let j = 0; j < line.length; j++) { + const seg = line[j]; + const column = cOffset + seg[COLUMN]; + + if (lineI === stopLine && column >= stopColumn) { + return; + } + + if (seg.length === 1) { + out.push([column]); + continue; + } + + out.push(getMapping(seg, column, sourcesOffset, namesOffset)); + } + } +} + +function addSection(options) { + + const { input } = options; + + const { sections } = input; + if (sections) { + return flatten(options); + } + + const sourcesOffset = options.sources.length; + const namesOffset = options.names.length; + + // sources and sourcesContent + if (!input.sourcesContent) { + input.sourcesContent = []; + } + input.sources.forEach((src, i) => { + options.sources.push(src); + options.sourcesContent.push(input.sourcesContent[i] || null); + }); + + // names + if (input.names) { + input.names.forEach((n) => { + options.names.push(n); + }); + } + + addMappings(options, sourcesOffset, namesOffset); + +} + +function flatten(options) { + + const { + input, + lineOffset, + columnOffset, + stopLine, + stopColumn + } = options; + + const { sections } = input; + + for (let i = 0, l = sections.length; i < l; i++) { + const { map, offset } = sections[i]; + + let sl = stopLine; + let sc = stopColumn; + if (i + 1 < sections.length) { + const nextOffset = sections[i + 1].offset; + sl = Math.min(stopLine, lineOffset + nextOffset.line); + + if (sl === stopLine) { + sc = Math.min(stopColumn, columnOffset + nextOffset.column); + } else if (sl < stopLine) { + sc = columnOffset + nextOffset.column; + } + } + + options.input = map; + options.lineOffset = lineOffset + offset.line; + options.columnOffset = columnOffset + offset.column; + options.stopLine = sl; + options.stopColumn = sc; + + addSection(options); + } +} + +const flattenSourceMaps = function(indexedMap, mapUrl) { + + const sections = indexedMap.sections; + if (!sections) { + return indexedMap; + } + + const decodedMappings = []; + const sources = []; + const sourcesContent = []; + const names = []; + + const lineOffset = 0; + const columnOffset = 0; + const stopLine = Infinity; + const stopColumn = Infinity; + + flatten({ + input: indexedMap, + + mapUrl, + + decodedMappings, + sources, + sourcesContent, + + names, + + lineOffset, + columnOffset, + stopLine, + stopColumn + }); + + indexedMap.sources = sources; + indexedMap.sourcesContent = sourcesContent; + indexedMap.names = names; + indexedMap.decodedMappings = decodedMappings; + + // console.log(decodedMappings); + + return indexedMap; +}; + +module.exports = { + flattenSourceMaps +}; diff --git a/node_modules/monocart-coverage-reports/lib/converter/ignore.js b/node_modules/monocart-coverage-reports/lib/converter/ignore.js new file mode 100644 index 0000000..636d7bb --- /dev/null +++ b/node_modules/monocart-coverage-reports/lib/converter/ignore.js @@ -0,0 +1,225 @@ +const Util = require('../utils/util.js'); + +const getNextN = (content, currentLine, item, locator) => { + + // v-8 ignore next N + if (content) { + const n = parseInt(content); + if (n && n > 0) { + return n; + } + return 1; + } + + // block comment not end of line, same line + if (item.block) { + // has code between comment and line end + const text = locator.getSlice(item.end, currentLine.end).trim(); + if (text) { + return 0; + } + } + + // v-8 ignore next + return 1; +}; + +const extendStart = (start, source) => { + // extend left, include + while (start > 0 && Util.isBlank(source[start - 1])) { + start -= 1; + } + return start; +}; + +const extendEnd = (end, source, maxLength) => { + // extend right, exclude + while (end < maxLength && Util.isBlank(source[end])) { + end += 1; + } + return end; +}; + +const addNextIgnore = (list, content, item, locator) => { + + const { lineParser, source } = locator; + const maxLength = source.length; + + const start = extendStart(item.start, source); + + // findLine 0-base + const currentLine = lineParser.findLine(item.end); + const n = getNextN(content, currentLine, item, locator); + + // console.log('current line', currentLine.line, 'lines', lines); + + // getLine 1-base + const line = currentLine.line + 1; + const endLine = locator.getLine(line + n); + const end = extendEnd(endLine ? endLine.end : maxLength, source, maxLength); + + const nextItem = { + type: 'next', + n, + start, + end + }; + + list.push(nextItem); +}; + +// both v8 or c8 +const getStartEndNextInfo = (content) => { + content = content.trim(); + + const start = 'start'; + const stop = 'stop'; + const next = 'next'; + if (content.startsWith(start)) { + return { + type: 'range', + value: stop + }; + } + if (content.startsWith(stop)) { + return { + type: 'range', + value: stop + }; + } + if (content.startsWith(next)) { + return { + type: 'next', + value: content.slice(next.length) + }; + } +}; + +const getDisableEnableNextInfo = (content) => { + content = content.trim(); + + const start = 'disable'; + const stop = 'enable'; + const next = 'ignore next'; + if (content.startsWith(start)) { + return { + type: 'range', + value: stop + }; + } + if (content.startsWith(stop)) { + return { + type: 'range', + value: stop + }; + } + if (content.startsWith(next)) { + return { + type: 'next', + value: content.slice(next.length) + }; + } +}; + + +const getIgnoreInfo = (content) => { + content = content.trim(); + + const v8_ignore = 'v8 ignore'; + if (content.startsWith(v8_ignore)) { + return getStartEndNextInfo(content.slice(v8_ignore.length)); + } + + const c8_ignore = 'c8 ignore'; + if (content.startsWith(c8_ignore)) { + return getStartEndNextInfo(content.slice(c8_ignore.length)); + } + + const node_coverage = 'node:coverage'; + if (content.startsWith(node_coverage)) { + return getDisableEnableNextInfo(content.slice(node_coverage.length)); + } + +}; + +const getIgnoredRanges = (locator, options) => { + if (!options.v8Ignore) { + return; + } + + const { lineParser, source } = locator; + const maxLength = source.length; + + const comments = lineParser.comments; + if (!Util.isList(comments)) { + return; + } + + const list = []; + let ignoreStart = null; + + comments.forEach((item) => { + const { + block, start, end, text + } = item; + + const content = block ? text.slice(2, -2) : text.slice(2); + const ignoreInfo = getIgnoreInfo(content); + if (!ignoreInfo) { + return; + } + + const { type, value } = ignoreInfo; + + if (ignoreStart) { + // v-8 ignore stop + if (type === 'range' && value === ignoreStart.value) { + ignoreStart.ignoreData.end = extendEnd(end, source, maxLength); + ignoreStart = null; + } + return; + } + + // v-8 ignore start + if (type === 'range') { + // add first for sort by start + const ignoreData = { + type, + start: extendStart(start, source), + end: start + }; + list.push(ignoreData); + ignoreStart = { + ignoreData, + value + }; + return; + } + + // next N + if (type === 'next') { + addNextIgnore(list, value.trim(), item, locator); + } + + }); + + // ignore not stop + if (ignoreStart) { + ignoreStart.end = locator.source.length; + ignoreStart = null; + } + + if (!list.length) { + return; + } + + // console.log('============================================='); + // console.log(list); + + return list; +}; + + +module.exports = { + getIgnoredRanges +}; diff --git a/node_modules/monocart-coverage-reports/lib/converter/info-branch.js b/node_modules/monocart-coverage-reports/lib/converter/info-branch.js new file mode 100644 index 0000000..211bd00 --- /dev/null +++ b/node_modules/monocart-coverage-reports/lib/converter/info-branch.js @@ -0,0 +1,93 @@ +const Util = require('../utils/util.js'); +module.exports = class InfoBranch { + constructor(data, original) { + const { + start, end, locations, type + } = data; + + this.start = start; + this.end = end; + this.locations = locations; + this.type = type; + this.data = data; + this.original = original; + } + + getRanges() { + return this.locations.map((item) => { + const range = { + start: item.start, + end: item.end, + count: item.count + }; + if (item.none) { + range.none = true; + } + if (item.ignored) { + range.ignored = true; + } + // for debug + if (Util.isDebug() && this.original) { + range.generatedStart = item.generatedStart; + range.generatedEnd = item.generatedEnd; + } + return range; + }); + } + + generate(locator) { + const groupLoc = { + start: this.start, + end: this.end + }; + Util.updateOffsetToLocation(locator, groupLoc); + const line = groupLoc.start.line; + + // remove ignored + // do NOT change previous number type to object, need used for sourcemap + const newLocations = this.locations.filter((it) => !it.ignored).map((it) => { + const item = { + start: it.start, + end: it.end, + none: it.none, + count: it.count + }; + + // [ { start:{line,column}, end:{line,column}, count }, ...] + Util.updateOffsetToLocation(locator, item); + + return item; + }); + + const map = { + loc: groupLoc, + type: this.type, + locations: newLocations.map((item) => { + const { + start, end, none + } = item; + if (none) { + // none with group start/end, should be empty for istanbul + return { + start: {}, + end: {} + }; + } + return { + start, + end + }; + + }), + line: line + }; + + const counts = newLocations.map((item) => item.count); + + return { + map, + counts + }; + } + +}; diff --git a/node_modules/monocart-coverage-reports/lib/converter/info-function.js b/node_modules/monocart-coverage-reports/lib/converter/info-function.js new file mode 100644 index 0000000..6cf96dc --- /dev/null +++ b/node_modules/monocart-coverage-reports/lib/converter/info-function.js @@ -0,0 +1,66 @@ +const Util = require('../utils/util.js'); +module.exports = class InfoFunction { + constructor(data, original) { + + const { + start, end, bodyStart, bodyEnd, functionName, count + } = data; + + this.start = start; + this.end = end; + this.bodyStart = bodyStart; + this.bodyEnd = bodyEnd; + this.count = count; + this.functionName = functionName; + this.data = data; + this.original = original; + } + + getName(index) { + return this.functionName || `(anonymous_${index})`; + } + + getRange(index) { + const range = { + name: this.getName(index), + start: this.start, + end: this.end, + count: this.count + }; + if (this.ignored) { + range.ignored = true; + } + // for debug + if (Util.isDebug() && this.original) { + range.generatedStart = this.data.generatedStart; + range.generatedEnd = this.data.generatedEnd; + } + return range; + } + + generate(locator, index) { + + const decl = { + start: this.start, + end: this.bodyStart + }; + + Util.updateOffsetToLocation(locator, decl); + + const loc = { + start: this.bodyStart, + end: this.end + }; + + Util.updateOffsetToLocation(locator, loc); + + const line = loc.start.line; + + return { + name: this.getName(index), + decl: decl, + loc: loc, + line: line + }; + } +}; diff --git a/node_modules/monocart-coverage-reports/lib/converter/info-statement.js b/node_modules/monocart-coverage-reports/lib/converter/info-statement.js new file mode 100644 index 0000000..24e3bee --- /dev/null +++ b/node_modules/monocart-coverage-reports/lib/converter/info-statement.js @@ -0,0 +1,43 @@ +const Util = require('../utils/util.js'); +module.exports = class InfoStatement { + constructor(data, original) { + const { + start, end, count + } = data; + + this.start = start; + this.end = end; + this.count = count; + this.data = data; + this.original = original; + } + + getRange() { + const range = { + start: this.start, + end: this.end, + count: this.count + }; + if (this.ignored) { + range.ignored = true; + } + // for debug + if (Util.isDebug() && this.original) { + range.generatedStart = this.data.generatedStart; + range.generatedEnd = this.data.generatedEnd; + } + return range; + } + + generate(locator) { + + const loc = { + start: this.start, + end: this.end + }; + + Util.updateOffsetToLocation(locator, loc); + + return loc; + } +}; diff --git a/node_modules/monocart-coverage-reports/lib/converter/untested.js b/node_modules/monocart-coverage-reports/lib/converter/untested.js new file mode 100644 index 0000000..cee9bad --- /dev/null +++ b/node_modules/monocart-coverage-reports/lib/converter/untested.js @@ -0,0 +1,315 @@ +const fs = require('fs'); +const path = require('path'); +const Util = require('../utils/util.js'); + +const { pathToFileURL, fileURLToPath } = require('url'); + +const { normalizeSourcePath, getSourcePathReplacer } = require('../utils/source-path.js'); + +// const EC = require('eight-colors'); +const { convertSourceMap } = require('../packages/monocart-coverage-vendor.js'); + +// ======================================================================================================== + +const resolveAllDirList = (input) => { + const dirs = Util.toList(input, ','); + if (!dirs.length) { + return; + } + const dirList = dirs.filter((it) => fs.existsSync(it)); + if (!dirList.length) { + return; + } + return dirList; +}; + +const resolveAllFilter = (input) => { + // for function handler + if (typeof input === 'function') { + return input; + } + + // for single minimatch pattern + if (input && typeof input === 'string') { + // string to multiple patterns "{...}" + const obj = Util.strToObj(input); + if (obj) { + input = obj; + } else { + return (filePath) => { + return Util.betterMinimatch(filePath, input); + }; + } + } + + // for patterns + if (input && typeof input === 'object') { + const patterns = Object.keys(input); + return (filePath) => { + for (const pattern of patterns) { + if (Util.betterMinimatch(filePath, pattern)) { + return input[pattern]; + } + } + // false if not matched + }; + } + + // default + return () => true; +}; + +const resolveAllOptions = (input) => { + if (!input) { + return; + } + + let dir; + let filter; + let transformer; + + if (typeof input === 'string') { + const obj = Util.strToObj(input); + if (obj) { + dir = obj.dir; + filter = obj.filter; + transformer = obj.transformer; + } else { + dir = input; + } + } else if (Array.isArray(input)) { + dir = input; + } else { + dir = input.dir; + filter = input.filter; + transformer = input.transformer; + } + + const dirList = resolveAllDirList(dir); + if (!dirList) { + return; + } + + const fileFilter = resolveAllFilter(filter); + const fileTransformer = typeof transformer === 'function' ? transformer : () => {}; + + return { + dirList, + fileFilter, + fileTransformer + }; +}; + +const resolveFileType = (fileType, filePath) => { + if (fileType === 'js' || fileType === 'css') { + return fileType; + } + const extname = path.extname(filePath); + if (['.css', '.scss', '.sass', '.less'].includes(extname)) { + return 'css'; + } + return 'js'; +}; + +const saveUntestedFileSource = async (entryFile, options) => { + const { + id, + url, + source, + sourceMap + } = entryFile; + // console.log('-', entry.sourcePath); + + const { cachePath } = Util.getCacheFileInfo('source', id, options.cacheDir); + if (fs.existsSync(cachePath)) { + return; + } + + // save source and sourceMap to separated json file + const sourceData = { + id, + url, + source, + sourceMap + }; + + // remove comments if not debug + if (!Util.isDebug()) { + sourceData.source = convertSourceMap.removeComments(source); + } + + // console.log('save untested file', id, url); + + await Util.saveSourceCacheFile(sourceData, options); + +}; + +const getUntestedCoverageData = async (entryList, options, coverageType) => { + + // save all empty coverage, 20 - 5(empty) + const dataId = Util.uid(15, 'empty'); + const results = { + id: dataId + }; + + if (coverageType === 'istanbul') { + results.type = 'istanbul'; + results.data = {}; + } else { + results.type = 'v8'; + results.data = []; + } + + const emptyCoverageList = []; + + // save all empty source and sourcemap + for (const entry of entryList) { + + // for raw report: source file + // id, url, source, sourceMap + await saveUntestedFileSource(entry, options); + + if (coverageType === 'istanbul') { + + // =============================================== + const item = { + path: fileURLToPath(entry.url), + statementMap: {}, + fnMap: {}, + branchMap: {}, + s: {}, + f: {}, + b: {} + }; + // object + results.data[item.path] = item; + emptyCoverageList.push(item); + + } else { + + // =============================================== + Util.setEmptyV8Coverage(entry); + + const item = { + ... entry + }; + delete item.source; + delete item.sourceMap; + + // array + results.data.push(item); + // will be parsed to AST and converted to V8 coverage + emptyCoverageList.push(entry); + + } + + } + + // for raw report: coverage file + const { cachePath } = Util.getCacheFileInfo('coverage', dataId, options.cacheDir); + await Util.writeFile(cachePath, JSON.stringify(results)); + + return emptyCoverageList; +}; + +const getEmptyCoverages = async (testedMap, options, coverageType, fileList, fileTransformer) => { + const sourceFilter = Util.getSourceFilter(options); + const sourcePathReplacer = getSourcePathReplacer(options); + const baseDir = options.baseDir; + + // console.log(fileList); + + const entryList = []; + for (const item of fileList) { + + const { fileType, filePath } = item; + const type = resolveFileType(fileType, filePath); + const url = pathToFileURL(filePath).toString(); + const source = Util.readFileSync(filePath); + const entry = { + empty: true, + type, + url, + source + }; + + // normalize sourcePath here + let sourcePath = normalizeSourcePath(url, baseDir); + if (sourcePathReplacer) { + const newSourcePath = sourcePathReplacer(sourcePath, entry); + if (typeof newSourcePath === 'string' && newSourcePath) { + sourcePath = newSourcePath; + } + } + + // console.log(sourcePath); + + if (testedMap.has(sourcePath)) { + continue; + } + + if (!sourceFilter(sourcePath)) { + continue; + } + + entry.sourcePath = sourcePath; + + await fileTransformer(entry, coverageType); + // after transformer + entry.id = Util.calculateSha1(entry.sourcePath + entry.source); + + entryList.push(entry); + } + + + // console.log('fileList', fileList); + if (!entryList.length) { + return; + } + + + // save empty coverage for merging raw reports + return getUntestedCoverageData(entryList, options, coverageType); +}; + +const getUntestedList = (testedMap, options, coverageType = 'v8') => { + const allOptions = resolveAllOptions(options.all); + // console.log('allOptions', all, allOptions); + if (!allOptions) { + return; + } + + const { + dirList, fileFilter, fileTransformer + } = allOptions; + + const fileList = []; + dirList.forEach((dir) => { + Util.forEachFile(dir, [], (fileName, fileDir) => { + const filePath = path.resolve(fileDir, fileName); + // return file extname for file type + const fileType = fileFilter(filePath); + if (fileType) { + fileList.push({ + filePath, + fileType, + fileDir, + fileName + }); + } + + }); + }); + + if (!fileList.length) { + return; + } + + return getEmptyCoverages(testedMap, options, coverageType, fileList, fileTransformer); + +}; + + +module.exports = { + getUntestedList +}; diff --git a/node_modules/monocart-coverage-reports/lib/default/options.js b/node_modules/monocart-coverage-reports/lib/default/options.js new file mode 100644 index 0000000..5c3280a --- /dev/null +++ b/node_modules/monocart-coverage-reports/lib/default/options.js @@ -0,0 +1,107 @@ +module.exports = { + + // {string} logging levels: off, error, info, debug + logging: 'info', + + // {string} Report name. Defaults to "Coverage Report". + name: 'Coverage Report', + + // {string} v8 or html for istanbul by default + // {array} multiple reports with options + // v8 report or istanbul supported reports + // reports: [ + // ['v8'], + // ['html', { + // subdir: 'my-sub-dir' + // }], + // 'lcov' + // ], + reports: '', + + // {string} output dir + outputDir: './coverage-reports', + + // {string|string[]} input raw dir(s) + inputDir: null, + + // {string} base dir for normalizing the relative source path, defaults to cwd + baseDir: null, + + // {string} coverage data dir, alternative to method `addFromDir()`, defaults to null + dataDir: null, + + // (V8 only) {function} A filter function to execute for each element in the V8 list. + // entryFilter: (entry) => { + // if (entry.url.indexOf('googleapis.com') !== -1) { + // return false; + // } + // return true; + // }, + entryFilter: null, + + // (V8 only) {function} A filter function to execute for each element in the sources which unpacked from the source map. + // sourceFilter: (sourcePath) => sourcePath.search(/src\/.+/) !== -1, + sourceFilter: null, + + // The combined filter for entryFilter and sourceFilter + filter: null, + + // {function} Source path handler. + // sourcePath: (filePath) => `wwwroot/${filePath}`, + sourcePath: null, + + // (V8 only) {string} Output [sub dir/]filename. Defaults to "index.html" + outputFile: 'index.html', + + // (V8 only) {boolean} Inline all scripts to the single HTML file. Defaults to false. + inline: false, + + // (V8 only) {string} Assets path if not inline. Defaults to "./assets" + assetsPath: './assets', + + // (Istanbul only) defaultSummarizer, sourceFinder + + // {boolean} Generate lcov.info file, same as lcovonly report. Defaults to false. + lcov: false, + + // options for adding empty coverage for all files + // all: { + // dir: ['src'], + // filter: (sourcePath) => true, + // transformer: (entry) => {} + // }, + all: null, + + // (V8 only) {boolean} Enable/Disable ignoring uncovered codes with the special comments: v8 ignore next/next N/start/stop + v8Ignore: true, + + // {string|function} Specify the report path, especially when there are multiple reports. Defaults to outputDir/index.html. + reportPath: null, + + // {array} watermarks for low/medium/high. Defaults to [50, 80] + // {object} { bytes:[50,80], statements:[50,80], branches:[50,80], functions:[50,80], lines:[50,80] } + watermarks: [50, 80], + + // {boolean} Indicates whether to clean previous files in output dir before generating report. Defaults to true. + clean: true, + + // {boolean} Indicates whether to clean previous cache in output dir before generating report. Defaults to false. + cleanCache: false, + + // {number} gc threshold + gc: null, + + // {boolean} Indicates whether to save source and sourcemap file for debug (require logging="debug") + sourceMap: false, + + // {function} Custom resolver for sourcemap content + sourceMapResolver: null, + + // {function} onEntry hook + // onEntry: async (entry) => {} + onEntry: null, + + // {function} onEnd hook + // onEnd: async (reportData) => {} + onEnd: null +}; diff --git a/node_modules/monocart-coverage-reports/lib/generate.js b/node_modules/monocart-coverage-reports/lib/generate.js new file mode 100644 index 0000000..a663513 --- /dev/null +++ b/node_modules/monocart-coverage-reports/lib/generate.js @@ -0,0 +1,494 @@ +const fs = require('fs'); +const path = require('path'); +const { fileURLToPath } = require('url'); +const EC = require('eight-colors'); + +const Util = require('./utils/util.js'); +const { convertV8List } = require('./converter/converter.js'); +const { resolveSourceMap } = require('./converter/collect-source-maps.js'); +const { StreamZip } = require('./packages/monocart-coverage-vendor.js'); + +// ======================================================================================================== +// built-in reports + +// istanbul +const { mergeIstanbulCoverage, saveIstanbulReports } = require('./istanbul/istanbul.js'); + +// v8 +const { mergeV8Coverage, saveV8Report } = require('./v8/v8.js'); + +// both +const { codecovReport } = require('./reports/codecov.js'); +const { codacyReport } = require('./reports/codacy.js'); + +const { consoleDetailsReport } = require('./reports/console-details.js'); +const { consoleSummaryReport } = require('./reports/console-summary.js'); + +const { markdownDetailsReport } = require('./reports/markdown-details.js'); +const { markdownSummaryReport } = require('./reports/markdown-summary.js'); + +const { rawReport } = require('./reports/raw.js'); + +const { customReport } = require('./reports/custom.js'); + +const allBuiltInReports = { + // v8 + 'v8': 'v8', + 'v8-json': 'v8', + + // istanbul + 'clover': 'istanbul', + 'cobertura': 'istanbul', + 'html': 'istanbul', + 'html-spa': 'istanbul', + 'json': 'istanbul', + 'json-summary': 'istanbul', + 'lcov': 'istanbul', + 'lcovonly': 'istanbul', + 'none': 'istanbul', + 'teamcity': 'istanbul', + 'text': 'istanbul', + 'text-lcov': 'istanbul', + 'text-summary': 'istanbul', + + // both + 'codecov': 'both', + 'codacy': 'both', + 'console-details': 'both', + 'console-summary': 'both', + 'markdown-details': 'both', + 'markdown-summary': 'both', + 'raw': 'both' +}; + +const bothBuiltInReports = { + 'codecov': codecovReport, + 'codacy': codacyReport, + + 'console-details': consoleDetailsReport, + 'console-summary': consoleSummaryReport, + + 'markdown-details': markdownDetailsReport, + 'markdown-summary': markdownSummaryReport, + + 'raw': rawReport +}; + +// ======================================================================================================== + +const getReportGroup = (reports, lcov, dataType) => { + + const reportMap = {}; + + const reportList = Util.toList(reports, ','); + reportList.forEach((it) => { + if (Util.isList(it)) { + // ["v8"], ["v8", {}] + const id = it[0]; + if (typeof id === 'string' && id) { + reportMap[id] = { + ... it[1] + }; + } + return; + } + if (typeof it === 'string' && it) { + reportMap[it] = {}; + } + }); + + // using default report if no reports + if (!Object.keys(reportMap).length) { + const defaultReport = dataType === 'v8' ? 'v8' : 'html'; + reportMap[defaultReport] = {}; + } + + // add lcovonly report after default report + if (lcov && !reportMap.lcovonly) { + reportMap.lcovonly = {}; + } + + // group v8 and istanbul + const groupMap = new Map(); + Object.keys(reportMap).forEach((k) => { + const options = reportMap[k]; + + let type = allBuiltInReports[k]; + if (!type) { + // for custom reporter + type = options.type || 'v8'; + } + + let group = groupMap.get(type); + if (!group) { + group = new Map(); + groupMap.set(type, group); + } + + group.set(k, options); + + }); + + // requires a default istanbul report if data is istanbul + if (dataType === 'istanbul' && !groupMap.has('istanbul')) { + const istanbulGroup = new Map(); + istanbulGroup.set('html', {}); + groupMap.set('istanbul', istanbulGroup); + } + + return groupMap; +}; + +// ======================================================================================================== + +// maybe v8 or to istanbul reports +const generateV8ListReports = async (v8list, coverageData, fileSources, options) => { + let istanbulReportPath; + // v8 to istanbul reports + if (options.reportGroup.has('istanbul')) { + const istanbulCoverageResults = await saveIstanbulReports(coverageData, fileSources, options); + istanbulReportPath = istanbulCoverageResults.reportPath; + } + + // v8 reports and v8 coverage results + // could be no v8 or v8-json, but requires v8 coverage results + const v8CoverageResults = await saveV8Report(v8list, options, istanbulReportPath); + return v8CoverageResults; +}; + +const getCoverageResults = async (dataList, sourceCache, options) => { + // get first and check v8list or istanbul data + const firstData = dataList[0]; + const dataType = firstData.type; + // console.log('data type', dataType); + + // init reports + options.reportGroup = getReportGroup(options.reports, options.lcov, dataType); + // console.log('reportGroup', options.reportGroup); + + // v8list + if (dataType === 'v8') { + // merge v8list first + const t1 = Date.now(); + const v8list = await mergeV8Coverage(dataList, sourceCache, options); + Util.logTime(`${EC.magenta('├')} [generate] merged v8 coverage data`, t1); + // console.log('after merge', v8list.map((it) => it.url)); + + const t2 = Date.now(); + const results = await convertV8List(v8list, options); + Util.logTime(`${EC.magenta('├')} [generate] converted coverage data`, t2); + + const { + v8DataList, coverageData, fileSources + } = results; + return generateV8ListReports(v8DataList, coverageData, fileSources, options); + } + + // istanbul data + const t3 = Date.now(); + const istanbulData = await mergeIstanbulCoverage(dataList, options); + Util.logTime(`${EC.magenta('├')} [generate] prepared istanbul coverage data`, t3); + const fileSources = options.fileSources || {}; + const results = await saveIstanbulReports(istanbulData, fileSources, options); + return results; +}; + +const generateCoverageReports = async (dataList, sourceCache, options) => { + const coverageResults = await getCoverageResults(dataList, sourceCache, options); + + // [ 'type', 'reportPath', 'name', 'watermarks', 'summary', 'files' ] + // console.log(Object.keys(coverageResults)); + + if (options.reportGroup.has('both')) { + const bothGroup = options.reportGroup.get('both'); + for (const [reportName, reportOptions] of bothGroup) { + const builtInHandler = bothBuiltInReports[reportName]; + const t1 = Date.now(); + if (builtInHandler) { + await builtInHandler(coverageResults, reportOptions, options); + } else { + await customReport(reportName, coverageResults, reportOptions, options); + } + Util.logTime(`${EC.magenta('├')} [generate] saved report: ${reportName}`, t1); + } + } + + return coverageResults; +}; + + +// ======================================================================================================== + +const getInputList = (mcr) => { + // get input dirs + const { inputDir, cacheDir } = mcr.options; + + const inputDirs = Util.toList(inputDir, ','); + + const inputList = inputDirs.filter((dir) => { + const hasDir = fs.existsSync(dir); + if (!hasDir) { + // could be empty + Util.logInfo(`Input coverage not exists: ${Util.relativePath(dir)}`); + } + return hasDir; + }); + + if (mcr.hasCache()) { + inputList.push(cacheDir); + } + + return inputList; +}; + +const addJsonData = async (mcr, dataList, sourceCache, input, filename) => { + const isCoverage = filename.startsWith('coverage-'); + const isSource = filename.startsWith('source-'); + if (isCoverage || isSource) { + let json = input; + if (typeof input === 'string') { + if (mcr.fileCache.has(filename)) { + json = mcr.fileCache.get(filename); + } else { + json = await Util.readJson(path.resolve(input, filename)); + } + } + if (json) { + if (isCoverage) { + dataList.push(json); + } else { + sourceCache.set(json.id, json); + } + } + } +}; + +const addDirData = async (mcr, dataList, sourceCache, dir) => { + const allFiles = fs.readdirSync(dir); + if (!allFiles.length) { + return; + } + for (const filename of allFiles) { + // only json file + if (filename.endsWith('.json')) { + await addJsonData(mcr, dataList, sourceCache, dir, filename); + } + } +}; + +const addZipData = async (mcr, dataList, sourceCache, dir) => { + const zip = new StreamZip({ + file: dir + }); + const entries = await zip.entries(); + for (const entry of Object.values(entries)) { + if (entry.isDirectory) { + continue; + } + const entryName = entry.name; + const filename = path.basename(entryName); + // console.log('============================', filename); + if (filename.endsWith('.json')) { + const buf = await zip.entryData(entryName); + const json = JSON.parse(buf.toString('utf-8')); + await addJsonData(mcr, dataList, sourceCache, json, filename); + } + + } + // Do not forget to close the file once you're done + await zip.close(); +}; + +const getInputData = async (mcr) => { + + const inputList = getInputList(mcr); + // console.log('input list', inputList); + + const dataList = []; + const sourceCache = new Map(); + + for (const dir of inputList) { + + const info = fs.statSync(dir); + if (info.isDirectory()) { + await addDirData(mcr, dataList, sourceCache, dir); + } else if (info.isFile()) { + await addZipData(mcr, dataList, sourceCache, dir); + } else { + Util.logError(`Invalid input: ${dir}`); + } + + } + + if (!dataList.length) { + const dirs = inputList.map((dir) => Util.relativePath(dir)); + Util.logError(`Not found coverage data in dir(s): ${dirs.join(', ')}`); + return; + } + + return { + dataList, + sourceCache + }; +}; + +// ======================================================================================================== + +const resolveEntrySource = (entry, sourceMapCache, sourceCache) => { + + const url = entry.url; + + // source from `source-id.json` + const sourceData = sourceCache.get(url); + if (sourceData) { + entry.source = sourceData.source; + return; + } + + // source for typescript file from source map cache + // Note: no runtime code but lineLengths + const tsExtensionsPattern = /\.([cm]?ts|[tj]sx)($|\?)/; + if (tsExtensionsPattern.test(url)) { + const sourcemapData = sourceMapCache[url]; + const lineLengths = sourcemapData && sourcemapData.lineLengths; + + // for fake source file (can not parse to AST) + if (lineLengths) { + let fakeSource = ''; + sourcemapData.lineLengths.forEach((length) => { + fakeSource += `${''.padEnd(length, '*')}\n`; + }); + entry.fake = true; + entry.source = fakeSource; + return; + } + + } + + // Note: it could be jsx format even extname is `.js` + const filePath = fileURLToPath(url); + if (fs.existsSync(filePath)) { + entry.source = fs.readFileSync(filePath).toString('utf8'); + } + +}; + +const resolveEntrySourceMap = (entry, sourceMapCache) => { + // sourcemap data + const sourcemapData = sourceMapCache[entry.url]; + if (sourcemapData) { + if (sourcemapData.data) { + entry.sourceMap = resolveSourceMap(sourcemapData.data, entry.url); + } + } +}; + +const readCoverageData = async (dir, filename, entryFilter, sourceCache) => { + + const content = await Util.readFile(path.resolve(dir, filename)); + if (!content) { + return; + } + const json = JSON.parse(content); + if (!json) { + return; + } + + // raw v8 json + let coverageData = json.result; + if (!Util.isList(coverageData)) { + return; + } + + // filter node internal files, should no anonymous for nodejs + coverageData = coverageData.filter((entry) => entry.url && entry.url.startsWith('file:')); + + const lengthBefore = coverageData.length; + coverageData = coverageData.filter(entryFilter); + const lengthAfter = coverageData.length; + Util.logFilter('entry filter (addFromDir):', lengthBefore, lengthAfter); + + if (!Util.isList(coverageData)) { + // Util.logDebug('No coverage data after filter'); + return; + } + + const sourceMapCache = json['source-map-cache'] || {}; + for (const entry of coverageData) { + resolveEntrySource(entry, sourceMapCache, sourceCache); + resolveEntrySourceMap(entry, sourceMapCache); + } + + return coverageData; +}; + +const readSourceList = async (dir, sourceList) => { + const sourceCache = new Map(); + + for (const filename of sourceList) { + const content = await Util.readFile(path.resolve(dir, filename)); + if (!content) { + continue; + } + const json = JSON.parse(content); + if (!json) { + continue; + } + if (json.url) { + sourceCache.set(json.url, json); + } + } + + return sourceCache; +}; + +const readFromDir = async (mcr, dir) => { + + if (!dir || !fs.existsSync(dir)) { + Util.logInfo(`Not found V8 coverage dir: ${dir}`); + return; + } + + const files = fs.readdirSync(dir); + + const coverageList = []; + const sourceList = []; + + files.forEach((filename) => { + // read all json files + if (filename.endsWith('.json')) { + // could be source files generated by register hooks + if (filename.startsWith('source-')) { + sourceList.push(filename); + } else { + coverageList.push(filename); + } + } + }); + + if (!coverageList.length) { + Util.logInfo(`No coverage files in the dir: ${dir}`); + return; + } + + const sourceCache = await readSourceList(dir, sourceList); + + const entryFilter = mcr.getEntryFilter(); + + for (const filename of coverageList) { + const coverageData = await readCoverageData(dir, filename, entryFilter, sourceCache); + if (coverageData) { + await mcr.add(coverageData); + } + } + + // GC + sourceCache.clear(); + +}; + +module.exports = { + getInputData, + readFromDir, + generateCoverageReports +}; diff --git a/node_modules/monocart-coverage-reports/lib/index.d.ts b/node_modules/monocart-coverage-reports/lib/index.d.ts new file mode 100644 index 0000000..dc1d83c --- /dev/null +++ b/node_modules/monocart-coverage-reports/lib/index.d.ts @@ -0,0 +1,606 @@ +declare namespace MCR { + + export interface V8CoverageEntry { + url: string; + + /** entry type */ + type?: "js" | "css"; + + /** css only */ + text?: string; + /** css only */ + ranges?: any[]; + + /** js only */ + source?: string; + /** js only */ + scriptId?: string; + /** js only */ + functions?: any[]; + + /** js only */ + sourceMap?: any; + /** js only */ + scriptOffset?: number; + /** js only */ + distFile?: string; + + /** empty coverage */ + empty?: boolean; + /** fake source */ + fake?: boolean; + + [key: string]: any; + } + + export type Watermarks = [number, number] | { + /** V8 only */ + bytes?: [number, number]; + statements: [number, number]; + branches?: [number, number]; + functions?: [number, number]; + lines?: [number, number]; + } + + export type ReportDescription = + ['v8'] | ["v8", { + /** + * defaults to `index.html` + */ + outputFile?: string; + inline?: boolean; + assetsPath?: string; + metrics?: Array<"bytes" | "statements" | "branches" | "functions" | "lines">; + }] | + ['v8-json'] | ["v8-json", { + /** + * defaults to `coverage-report.json` + */ + outputFile?: string; + }] | + ['clover'] | ['clover', { + file?: string; + }] | + ['cobertura'] | ['cobertura', { + file?: string; + timestamp?: string; + projectRoot?: string; + }] | + ['html'] | ['html', { + subdir?: string; + verbose?: boolean; + linkMapper?: any; + skipEmpty?: boolean; + }] | + ['html-spa'] | ['html-spa', { + subdir?: string; + verbose?: boolean; + linkMapper?: any; + skipEmpty?: boolean; + metricsToShow?: Array<"statements" | "branches" | "functions" | "lines">; + }] | + ['json'] | ['json', { + file?: string; + }] | + ['json-summary'] | ['json-summary', { + file?: string; + }] | + ['lcov'] | ['lcov', { + file?: string; + projectRoot?: string; + }] | + ['lcovonly'] | ['lcovonly', { + file?: string; + projectRoot?: string; + }] | + ['none'] | + ['teamcity'] | ['teamcity', { + file?: string; + blockName?: string; + }] | + ['text'] | ['text', { + file?: string; + maxCols?: number; + skipEmpty?: boolean; + skipFull?: boolean; + }] | + ['text-lcov'] | ['text-lcov', { + projectRoot?: string; + }] | + ['text-summary'] | ['text-summary', { + file?: string; + }] | + ['codecov'] | ["codecov", { + /** + * defaults to `codecov.json` + */ + outputFile?: string; + }] | + ['codacy'] | ["codacy", { + /** + * defaults to `codacy.json` + */ + outputFile?: string; + }] | + ['console-summary'] | ['console-summary', { + metrics?: Array<"bytes" | "statements" | "branches" | "functions" | "lines">; + }] | + ['console-details'] | ['console-details', { + maxCols?: number; + skipPercent?: number; + metrics?: Array<"bytes" | "statements" | "branches" | "functions" | "lines">; + filter?: string | { + [pattern: string]: boolean; + } | ((file: CoverageFile) => boolean); + }] | + ['markdown-summary'] | ['markdown-summary', { + color: 'unicode' | 'html' | 'tex' | string; + metrics?: Array<"bytes" | "statements" | "branches" | "functions" | "lines">; + /** + * defaults to `coverage-summary.md` + */ + outputFile?: string; + }] | + ['markdown-details'] | ['markdown-details', { + baseUrl?: string; + color: 'unicode' | 'html' | 'tex' | string; + maxCols?: number; + skipPercent?: number; + metrics?: Array<"bytes" | "statements" | "branches" | "functions" | "lines">; + filter?: string | { + [pattern: string]: boolean; + } | ((file: CoverageFile) => boolean); + /** + * defaults to `coverage-details.md` + */ + outputFile?: string; + }] | + ['raw'] | ['raw', { + merge?: boolean; + zip?: boolean; + outputDir?: string; + }] | + [string] | [string, { + type?: "v8" | "istanbul" | "both" | string; + [key: string]: any; + }]; + + export type AddedResults = { + id: string; + path: string; + type: "v8" | "istanbul"; + data: any; + }; + + + export interface MetricsSummary { + covered: number; + uncovered?: number; + total: number; + pct: number | ""; + status: "low" | "medium" | "high" | "unknown"; + /** V8 lines only */ + blank?: number; + /** V8 lines only */ + comment?: number; + } + + export interface CoverageSummary { + /** V8 only */ + bytes?: MetricsSummary; + statements: MetricsSummary; + branches: MetricsSummary; + functions: MetricsSummary; + lines: MetricsSummary; + } + + /** V8 only */ + export interface CoverageRange { + start: number; + end: number; + count: number; + /** ignored by special comment which starts with `v8 ignore` */ + ignored?: boolean; + /** + * branch only, for example: + * there is only `if` branch but no `else` branch, then `none` will be true, it shows `else path uncovered` + */ + none?: boolean; + /** function only, function name */ + name?: boolean; + } + + export interface IgnoredRange { + start: number; + end: number; + /** ignore type: `next` or `range` */ + type: string; + /** n lines for `next` type */ + n?: number; + } + + export interface CoverageFile { + sourcePath: string; + summary: CoverageSummary; + /** V8 only */ + url?: string; + /** V8 only */ + id?: string; + /** V8 only */ + type?: string; + /** V8 only */ + source?: string; + /** V8 only */ + distFile?: string; + /** V8 only */ + js?: boolean; + /** V8 only */ + data?: { + bytes?: CoverageRange[]; + statements?: CoverageRange[]; + branches?: CoverageRange[]; + functions?: CoverageRange[]; + ignores?: IgnoredRange[]; + lines?: { + /** + * key: line number; + * number: hits (0 means uncovered); + * string: partial covered + */ + [key: string]: number | string; + }; + extras?: { + /** + * key: line number; + * b: blank; + * c: comment; + * i: ignored; + */ + [key: string]: "b" | "c" | "i"; + } + } + } + + export type CoverageResults = { + type: "v8" | "istanbul"; + reportPath: string; + version: string; + name: string; + watermarks: Watermarks; + summary: CoverageSummary; + files: CoverageFile[]; + }; + + export type LoggingType = "off" | "error" | "info" | "debug"; + export interface CoverageReportOptions { + + /** {string} logging levels: off, error, info, debug */ + logging?: LoggingType; + + /** {string} Report name. Defaults to "Coverage Report". */ + name?: string; + + /** + * + * {string} 'v8', 'v8,console-details' + * + * {array} ['v8'], ['v8', ['console-details', { skipPercent: 80 }]] + * + * By default, `v8` for V8 data, `html` for Istanbul data + */ + reports?: string | (string | ReportDescription)[]; + + /** {string} output dir */ + outputDir?: string; + + /** {string|string[]} input raw dir(s) */ + inputDir?: string | string[]; + + /** {string} base dir for normalizing the relative source path, defaults to cwd */ + baseDir?: string; + + /** {string} coverage data dir, alternative to method `addFromDir()`, defaults to null */ + dataDir?: string; + + /** (V8 only) + * + * {string} `minimatch` pattern for entry url; + * {object} multiple patterns; + * {function} A filter function for each entry file in the V8 list. + */ + entryFilter?: string | { + [pattern: string]: boolean; + } | ((entry: V8CoverageEntry) => boolean); + + /** (V8 only) + * + * {string} `minimatch` pattern for source path; + * {object} multiple patterns; + * {function} A filter function for each source path when the source is unpacked from the source map. + */ + sourceFilter?: string | { + [pattern: string]: boolean; + } | ((sourcePath: string) => boolean); + + /** + * The combined filter for entryFilter and sourceFilter + */ + filter?: string | { + [pattern: string]: boolean; + } | ((input: string | V8CoverageEntry) => boolean); + + /** + * {function} Source path handler. + * + * {object} Replace key with value. + * */ + sourcePath?: ((filePath: string, info: { + /** the related dist file of current source file */ + distFile?: string; + [key: string]: any; + }) => string) | { + [key: string]: string; + }; + + + /** (V8 only) {string} Output [sub dir/]filename. Defaults to "index.html" */ + outputFile?: string; + /** (V8 only) {boolean} Inline all scripts to the single HTML file. Defaults to false. */ + inline?: boolean; + /** (V8 only) {string} Assets path if not inline. Defaults to "./assets" */ + assetsPath?: string; + + /** (Istanbul only) defaultSummarizer, sourceFinder */ + + /** {boolean} Generate lcov.info file, same as lcovonly report. Defaults to false. */ + lcov?: boolean; + + /** + * options for adding empty coverage for all files + */ + all?: string | string[] | { + /** the dir(s) of all files */ + dir: string | string[]; + + /** + * the file filter is triggered before `sourceFilter`, no need to use it in normal case + * the filter could return the file type, if true, defaults to css if ".css" otherwise is js + * {string} `minimatch` pattern for file path; {object} multiple patterns; {function} A filter function for file path; + */ + filter?: string | { + [pattern: string]: "js" | "css" | boolean; + } | ((filePath: string) => "js" | "css" | boolean); + + /** + * the file transformer for source and sourceMap + * some of untested files like .ts/.jsx/.vue can not be parsed to AST directly by acorn + * so this is the function which can transform the original source to generated source and sourceMap + */ + transformer?: (entry: any) => Promise; + + }; + + /** (V8 only) {boolean} Enable/Disable ignoring uncovered codes with the special comments: v8 ignore next/next N/start/stop */ + v8Ignore?: boolean; + + /** {string|function} Specify the report path, especially when there are multiple reports. Defaults to outputDir/index.html. */ + reportPath?: string | (() => string); + + /** {array} watermarks for low/medium/high. Defaults to [50, 80] + * {object} { bytes:[50,80], statements:[50,80], branches:[50,80], functions:[50,80], lines:[50,80] } */ + watermarks?: Watermarks; + + /** + * {boolean} Indicates whether to clean previous reports in output dir before generating new reports. Defaults to true. + * + * If true, the API `clean()` will execute automatically. + * */ + clean?: boolean; + + /** + * {boolean} Indicates whether to clean previous cache in output dir on start. Defaults to false. + * + * If true, the API `cleanCache()` will execute automatically. + */ + cleanCache?: boolean; + + /** + * {number} gc threshold + * for example: sets gc to 1024 means that force gc when the memory > 1024M at certain critical stages + * https://nodejs.org/docs/latest/api/v8.html#v8setflagsfromstringflags + */ + gc?: number; + + /** + * {boolean} Indicates whether to save source and sourcemap file for debug (require logging="debug") + */ + sourceMap?: boolean; + + /** + * {function} Custom resolver for sourcemap content + */ + sourceMapResolver?: (url: string, defaultResolver: Function) => Promise; + + /** (V8 only) {function} onEntry hook */ + onEntry?: (entry: V8CoverageEntry) => Promise; + + /** {function} onEnd hook */ + onEnd?: (coverageResults: CoverageResults | undefined) => Promise; + + [key: string]: any; + } + + export interface McrCliOptions extends CoverageReportOptions { + + /** (CLI only) {function} onStart hook */ + onStart?: (coverageReport: CoverageReport) => Promise; + + /** (CLI only) {function} onReady hook before adding coverage data. + * + * Sometimes, the child process has not yet finished writing the coverage data, and it needs to wait here. + */ + onReady?: (coverageReport: CoverageReport, nodeV8CoverageDir: string, subprocess: any) => Promise; + + } + + export class CoverageReport { + + /** + * @param options coverage report options + */ + constructor(options?: CoverageReportOptions); + + /** add coverage data + * + * @param coverageData {array} V8 format, {object} Istanbul format */ + add: (coverageData: any[] | any) => Promise; + + /** + * add V8 coverage from a dir + * @param dir node v8 coverage dir + */ + addFromDir: (dir: string) => Promise; + + /** generate report */ + generate: () => Promise; + + /** check if cache exists */ + hasCache: () => boolean; + + /** clean previous cache, return `false` if no cache */ + cleanCache: () => boolean; + + /** clean previous reports except cache dir and v8 coverage dir */ + clean: () => void; + + /** get entry filter handler, it can be used to filter the coverage data list before adding it. */ + getEntryFilter: () => ((entry: V8CoverageEntry) => boolean); + + /** load config file. + * + * @param configFile custom config file path + * + * Supports loading default config file if no custom config specified: + 'mcr.config.js', + 'mcr.config.cjs', + 'mcr.config.mjs', + 'mcr.config.json', + 'mcr.config.ts' + */ + loadConfig: (configFile?: string) => Promise; + } + + //===================================================================================================== + + export interface CoverageSnapshot { + type: "v8" | "istanbul"; + summary: { + bytes?: string; + statements: string; + branches: string; + functions: string; + lines: string; + }, + files: { + [sourcePath: string]: { + bytes?: string; + statements: string; + branches: string; + functions: string; + lines: string; + uncoveredLines: string; + extras: string; + } + } + } + + /** get snapshot from coverage report data */ + export function getSnapshot(coverageResults: CoverageResults): CoverageSnapshot; + + /** diff two snapshots */ + export function diffSnapshot(oldData: CoverageSnapshot, newData: CoverageSnapshot, diffOptions: { + skipEqual?: boolean; + showSummary?: boolean; + maxCols?: number; + metrics?: Array<"bytes" | "statements" | "branches" | "functions" | "lines">; + }): { + change: boolean; + results: any[]; + message: string; + }; + + //===================================================================================================== + + export class CoverageClient { + /** start js coverage */ + startJSCoverage: () => Promise; + /** stop and return js coverage */ + stopJSCoverage: () => Promise; + + /** start css coverage */ + startCSSCoverage: () => Promise; + /** stop and return css coverage */ + stopCSSCoverage: () => Promise; + + /** start both js and css coverage */ + startCoverage: () => Promise; + /** stop and return both js and css coverage */ + stopCoverage: () => Promise; + + /** write the coverage started by NODE_V8_COVERAGE to disk on demand, returns v8 coverage dir */ + writeCoverage: () => Promise; + + /** get istanbul coverage data + * @param coverageKey defaults to `__coverage__` + */ + getIstanbulCoverage: (coverageKey?: string) => Promise; + + close: () => Promise + } + + /** Adapt to the CDPSession of Playwright or Puppeteer */ + export interface CDPSession { + send: (method: string, params?: any) => Promise; + on: (type: string, handler: (e: any) => void) => void; + detach: () => Promise; + } + + /** custom websocket CDPSession */ + export class WSSession implements CDPSession { + constructor(ws: any); + send: (method: string, params?: any) => Promise; + on: (type: string, handler: (e: any) => void) => void; + detach: () => Promise; + } + + export interface CDPOptions { + /** Adapt to the CDPSession of Playwright or Puppeteer */ + session?: CDPSession; + /** websocket debugger url */ + url?: string; + /** debugger port, defaults to 9222 */ + port?: number; + /** debugger host, defaults to localhost */ + host?: string; + /** enable https, defaults to false (http) */ + secure?: boolean; + /** target filter, defaults to first page */ + target?: (targets: any) => any; + /** websocket options */ + ws?: any; + /** timeout, defaults to 10 * 1000 */ + timeout?: number; + } + + export function CDPClient(cdpOptions: CDPOptions): Promise; + + export const Util: { + initLoggingLevel: (logging: LoggingType) => string; + }; + +} + +/** create coverage report */ +declare function MCR(options?: MCR.CoverageReportOptions): MCR.CoverageReport; + +export = MCR; diff --git a/node_modules/monocart-coverage-reports/lib/index.js b/node_modules/monocart-coverage-reports/lib/index.js new file mode 100644 index 0000000..802f81f --- /dev/null +++ b/node_modules/monocart-coverage-reports/lib/index.js @@ -0,0 +1,280 @@ +const fs = require('fs'); +const path = require('path'); +const { pathToFileURL } = require('url'); +const EC = require('eight-colors'); + +const defaultOptions = require('./default/options.js'); +const Util = require('./utils/util.js'); + +const { initV8ListAndSourcemap } = require('./v8/v8.js'); +const { + getInputData, readFromDir, generateCoverageReports +} = require('./generate.js'); +const { getSnapshot, diffSnapshot } = require('./utils/snapshot.js'); + +const WSSession = require('./client/ws-session.js'); +const CDPClient = require('./client/cdp-client.js'); + +const resolveConfigOptions = async (configPath) => { + // json format + const ext = path.extname(configPath); + if (ext === '.json' || configPath.slice(-2) === 'rc') { + return JSON.parse(Util.readFileSync(configPath)); + } + + let configOptions; + let err; + try { + configOptions = await import(pathToFileURL(configPath)); + } catch (ee) { + err = ee; + } + + if (err) { + Util.logError(`ERROR: failed to load config "${configPath}": ${err && err.message} `); + return; + } + + // could be multiple level default + while (configOptions && configOptions.default) { + configOptions = configOptions.default; + } + + return configOptions; +}; + +class CoverageReport { + + constructor(options = {}) { + this.cacheDirName = '.cache'; + this.constructorOptions = options; + this.options = { + ... defaultOptions, + ... options + }; + this.initOptions(); + this.fileCache = new Map(); + } + + initOptions(force) { + + if (this.fixedOptions && !force) { + return; + } + + // before clean cache, do no call initOptions again in hasCache + this.fixedOptions = true; + + // init logging for clean after generated + this.logging = Util.initLoggingLevel(this.options.logging); + + if (Util.isNum(this.options.gc)) { + Util.setGC(this.options.gc); + } + + // init outputDir + const outputDir = `${this.options.outputDir || defaultOptions.outputDir}`; + this.options.outputDir = outputDir; + + // cache dir, it is useful if runs in multiple processes. + // cache coverage- data and source- files + // it will be removed after generated if logging it not debug. + const cacheDir = path.resolve(outputDir, this.cacheDirName); + this.options.cacheDir = cacheDir; + + // If true, the API `cleanCache()` will execute automatically. + if (this.options.cleanCache) { + this.cleanCache(); + } + + } + + // add coverage data: {array} V8 format, {object} Istanbul format + async add(data) { + + const time_start = Date.now(); + + this.initOptions(); + + if (!Util.checkCoverageData(data)) { + Util.logError(`${this.options.name}: The added coverage data must be Array(V8) or Object(Istanbul)`); + return; + } + + const dataId = Util.uid(); + const results = { + id: dataId + }; + + if (Array.isArray(data)) { + results.type = 'v8'; + // could be empty list after entryFilter + results.data = await initV8ListAndSourcemap(this, data); + } else { + results.type = 'istanbul'; + results.data = data; + } + + // save data to cache + const { cacheName, cachePath } = Util.getCacheFileInfo('coverage', dataId, this.options.cacheDir); + this.fileCache.set(cacheName, results); + await Util.writeFile(cachePath, JSON.stringify(results)); + + Util.logTime(`added coverage data: ${results.type}`, time_start); + + return results; + } + + // add coverage from dir + async addFromDir(dir) { + const time_start = Date.now(); + await readFromDir(this, dir); + Util.logTime(`added from dir: ${dir}`, time_start); + } + + // generate report + async generate() { + + const time_start = Date.now(); + + this.initOptions(); + + const dataDir = this.options.dataDir; + if (dataDir) { + await this.addFromDir(dataDir); + } + + const inputData = await getInputData(this); + if (!inputData) { + return; + } + + // GC, no OOM + this.fileCache.clear(); + + const { dataList, sourceCache } = inputData; + + // empty output dir except cache dir before generate reports + const outputDir = this.options.outputDir; + + if (fs.existsSync(outputDir)) { + // if assets dir is out of output dir will be ignore + if (this.options.clean) { + this.clean(); + } + } else { + fs.mkdirSync(outputDir, { + recursive: true + }); + } + + Util.logTime(`${EC.magenta('├')} [generate] prepared coverage data`, time_start); + + const coverageResults = await generateCoverageReports(dataList, sourceCache, this.options); + + const onEnd = this.options.onEnd; + if (typeof onEnd === 'function') { + await onEnd.call(this, coverageResults); + } + + // remove cache dir after finished + if (!Util.isDebug()) { + Util.rmSync(this.options.cacheDir); + } + + let reportPath = ''; + if (coverageResults.reportPath) { + reportPath = EC.cyan(coverageResults.reportPath); + } + Util.logTime(`generated coverage reports: ${reportPath}`, time_start); + + return coverageResults; + } + + // check if cache dir exists + hasCache() { + this.initOptions(); + return fs.existsSync(this.options.cacheDir); + } + + // cache clean dir + cleanCache() { + // clean previous artifacts + if (this.hasCache()) { + Util.rmSync(this.options.cacheDir); + return true; + } + return false; + } + + // clean previous reports except cache dir and v8 coverage dir + clean() { + const outputDir = this.options.outputDir; + let v8DirName; + const nodeV8CoverageDir = process.env.NODE_V8_COVERAGE; + if (nodeV8CoverageDir) { + v8DirName = path.relative(outputDir, nodeV8CoverageDir); + } + fs.readdirSync(outputDir).forEach((itemName) => { + if (itemName === this.cacheDirName) { + return; + } + if (itemName === v8DirName) { + return; + } + Util.rmSync(path.resolve(outputDir, itemName)); + }); + } + + // get entry filter handler + getEntryFilter() { + return Util.getEntryFilter(this.options); + } + + // load config file + async loadConfig(customConfigFile) { + + const configPath = Util.findUpConfig(customConfigFile); + if (!configPath) { + if (customConfigFile) { + Util.logError(`The config file does not exist: ${customConfigFile}`); + } + // not found config + return; + } + + const configOptions = await resolveConfigOptions(configPath); + if (!configOptions) { + // failed to load config options + if (customConfigFile) { + Util.logError(`Failed to load config file: ${customConfigFile}`); + } + return; + } + + Util.logInfo(`Loaded: ${EC.cyan(Util.relativePath(configPath))}`); + + // init options again + this.options = { + ... defaultOptions, + ... configOptions, + ... this.constructorOptions + }; + this.initOptions(true); + + } + +} + +/** create coverage report */ +const MCR = function(options) { + return new CoverageReport(options); +}; +MCR.CoverageReport = CoverageReport; +MCR.getSnapshot = getSnapshot; +MCR.diffSnapshot = diffSnapshot; +MCR.WSSession = WSSession; +MCR.CDPClient = CDPClient; +MCR.Util = Util; + +module.exports = MCR; diff --git a/node_modules/monocart-coverage-reports/lib/index.mjs b/node_modules/monocart-coverage-reports/lib/index.mjs new file mode 100644 index 0000000..3ebf53c --- /dev/null +++ b/node_modules/monocart-coverage-reports/lib/index.mjs @@ -0,0 +1,9 @@ +import MCR from './index.js'; +export default MCR; +export const CoverageReport = MCR.CoverageReport; +export const getSnapshot = MCR.getSnapshot; +export const diffSnapshot = MCR.diffSnapshot; + +export const WSSession = MCR.WSSession; +export const CDPClient = MCR.CDPClient; +export const Util = MCR.Util; diff --git a/node_modules/monocart-coverage-reports/lib/istanbul/istanbul-summary.js b/node_modules/monocart-coverage-reports/lib/istanbul/istanbul-summary.js new file mode 100644 index 0000000..a92d312 --- /dev/null +++ b/node_modules/monocart-coverage-reports/lib/istanbul/istanbul-summary.js @@ -0,0 +1,73 @@ +const istanbulLibReport = require('istanbul-lib-report'); + +const ReportBase = istanbulLibReport.ReportBase; +class IstanbulSummary extends ReportBase { + + onStart(root, context) { + this.context = context; + this.summary = {}; + this.files = []; + } + + addStatus(data) { + Object.keys(data).forEach((k) => { + const item = data[k]; + // low, medium, high, unknown + item.status = this.context.classForPercent(k, item.pct); + }); + } + + onSummary(node) { + if (!node.isRoot()) { + return; + } + this.summary = node.getCoverageSummary().data; + this.addStatus(this.summary); + } + + onDetail(node) { + const fileSummary = node.getCoverageSummary().data; + this.addStatus(fileSummary); + const sourcePath = node.getQualifiedName(); + + const fileCoverage = node.getFileCoverage(); + const lines = fileCoverage.getLineCoverage(); + // no extras for istanbul + const extras = {}; + + this.files.push({ + sourcePath, + summary: fileSummary, + data: { + lines, + extras + } + }); + } + + onEnd() { + // console.log('onEnd'); + } + + getReport() { + + // remove branchesTrue + delete this.summary.branchesTrue; + + // add uncovered + Object.keys(this.summary).forEach((id) => { + const item = this.summary[id]; + item.uncovered = item.total - item.covered; + }); + + // console.log(this.summary); + + return { + summary: this.summary, + files: this.files + }; + } +} + + +module.exports = IstanbulSummary; diff --git a/node_modules/monocart-coverage-reports/lib/istanbul/istanbul.js b/node_modules/monocart-coverage-reports/lib/istanbul/istanbul.js new file mode 100644 index 0000000..4636cf7 --- /dev/null +++ b/node_modules/monocart-coverage-reports/lib/istanbul/istanbul.js @@ -0,0 +1,170 @@ +const fs = require('fs'); +const path = require('path'); +const istanbulReports = require('istanbul-reports'); +const istanbulLibCoverage = require('istanbul-lib-coverage'); +const istanbulLibReport = require('istanbul-lib-report'); +const EC = require('eight-colors'); + +const Util = require('../utils/util.js'); +const IstanbulSummary = require('./istanbul-summary.js'); + +const { initIstanbulSourcePath } = require('../utils/source-path.js'); +const { getUntestedList } = require('../converter/untested.js'); + +const findHtmlPath = (outputDir) => { + const defaultHtml = path.resolve(outputDir, 'index.html'); + if (fs.existsSync(defaultHtml)) { + return defaultHtml; + } + + const htmlList = []; + Util.forEachFile(outputDir, ['.html'], (name, dir) => { + const htmlPath = path.resolve(dir, name); + if (name === 'index.html') { + htmlList.unshift(htmlPath); + return 'break'; + } + htmlList.push(htmlPath); + }); + + if (htmlList.length) { + return htmlList[0]; + } + + return defaultHtml; + +}; + +const saveIstanbulReports = (coverageData, fileSources, options) => { + + coverageData = initIstanbulSourcePath(coverageData, fileSources, options); + + const coverageMap = istanbulLibCoverage.createCoverageMap(coverageData); + + const defaultWatermarks = { + statements: [50, 80], + branches: [50, 80], + functions: [50, 80], + lines: [50, 80] + }; + const watermarks = Util.resolveWatermarks(defaultWatermarks, options.watermarks); + + // https://github.com/istanbuljs/istanbuljs/tree/master/packages/istanbul-lib-report + + // defaultSummarizer and sourceFinder can be passed from options + const contextOptions = { + coverageMap, + // The summarizer to default to (may be overridden by some reports) + // values can be nested/flat/pkg. Defaults to 'pkg' + defaultSummarizer: options.defaultSummarizer || 'nested', + + dir: options.outputDir, + watermarks, + sourceFinder: (filePath) => { + + // console.log(`find file source: ${filePath}`); + + if (fileSources) { + const source = fileSources[filePath]; + if (source) { + return source; + } + } + + if (typeof options.sourceFinder === 'function') { + const source = options.sourceFinder(filePath); + if (source) { + return source; + } + } + + if (fs.existsSync(filePath)) { + return fs.readFileSync(filePath, 'utf8'); + } + + // console.log('Not found source file:', filePath); + + return `Not found source file: ${filePath}`; + } + }; + + // create a context for report generation + const context = istanbulLibReport.createContext(contextOptions); + + const istanbulGroup = options.reportGroup.get('istanbul'); + // already has + if (istanbulGroup) { + for (const [reportName, reportOptions] of istanbulGroup) { + const t1 = Date.now(); + const report = istanbulReports.create(reportName, reportOptions); + report.execute(context); + Util.logTime(`${EC.magenta('├')} [generate] saved report: ${reportName}`, t1); + } + } + + // add watermarks and color + const coverageReport = new IstanbulSummary(); + coverageReport.execute(context); + + const reportPath = Util.resolveReportPath(options, () => { + // find first index.html path for preview + const htmlPath = findHtmlPath(options.outputDir); + return Util.relativePath(htmlPath); + }); + + const coverageResults = { + type: 'istanbul', + reportPath, + version: Util.version, + name: options.name, + watermarks: contextOptions.watermarks, + // summary and files + ... coverageReport.getReport() + }; + + return coverageResults; +}; + +const addUntestedFiles = async (istanbulData, options) => { + const testedMap = new Map(); + Object.keys(istanbulData).forEach((filePath) => { + const sourcePath = Util.relativePath(filePath); + testedMap.set(sourcePath, true); + }); + + // untested files + const untestedList = await getUntestedList(testedMap, options, 'istanbul'); + if (!untestedList) { + return; + } + + // console.log('istanbul untestedList', untestedList); + untestedList.forEach((item) => { + if (!istanbulData[item.path]) { + istanbulData[item.path] = istanbulLibCoverage.createFileCoverage(item); + } + }); + +}; + +const mergeIstanbulDataList = (dataList, options) => { + const istanbulCoverageList = dataList.map((it) => it.data); + const coverageMap = istanbulLibCoverage.createCoverageMap(); + istanbulCoverageList.forEach((coverage) => { + coverageMap.merge(coverage); + }); + const istanbulData = coverageMap.toJSON(); + return istanbulData; +}; + +const mergeIstanbulCoverage = async (dataList, options) => { + const istanbulData = mergeIstanbulDataList(dataList, options); + await addUntestedFiles(istanbulData, options); + return istanbulData; +}; + +module.exports = { + saveIstanbulReports, + mergeIstanbulDataList, + mergeIstanbulCoverage +}; diff --git a/node_modules/monocart-coverage-reports/lib/packages/monocart-coverage-assets.js b/node_modules/monocart-coverage-reports/lib/packages/monocart-coverage-assets.js new file mode 100644 index 0000000..19258d9 --- /dev/null +++ b/node_modules/monocart-coverage-reports/lib/packages/monocart-coverage-assets.js @@ -0,0 +1,4 @@ +module.exports = { + "template": "\n\n\n \n \n \n {title}\n \n\n\n
\n \n \n \n
\n{content}\n\n\n", + "monocart-coverage-app": "var a=(r,e)=>()=>(e||r((e={exports:{}}).exports,e),e.exports);var s=a((b,o)=>{o.exports=`(()=>{var x=(e,n)=>()=>(n||e((n={exports:{}}).exports,n),n.exports);var S=x((V,R)=>{var _=0,p=-3;function b(){this.table=new Uint16Array(16),this.trans=new Uint16Array(288)}function N(e,n){this.source=e,this.sourceIndex=0,this.tag=0,this.bitcount=0,this.dest=n,this.destLen=0,this.ltree=new b,this.dtree=new b}var y=new b,k=new b,w=new Uint8Array(30),h=new Uint16Array(30),L=new Uint8Array(30),T=new Uint16Array(30),O=new Uint8Array([16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15]),A=new b,c=new Uint8Array(320);function D(e,n,r,a){var t,i;for(t=0;t>>=1,n}function u(e,n,r){if(!n)return r;for(;e.bitcount<24;)e.tag|=e.source[e.sourceIndex++]<>>16-n;return e.tag>>>=n,e.bitcount-=n,a+r}function v(e,n){for(;e.bitcount<24;)e.tag|=e.source[e.sourceIndex++]<>>=1,++t,r+=n.table[t],a-=n.table[t];while(a>=0);return e.tag=i,e.bitcount-=t,n.trans[r+a]}function C(e,n,r){var a,t,i,o,s,f;for(a=u(e,5,257),t=u(e,5,1),i=u(e,4,4),o=0;o<19;++o)c[o]=0;for(o=0;o8;)e.sourceIndex--,e.bitcount-=8;if(n=e.source[e.sourceIndex+1],n=256*n+e.source[e.sourceIndex],r=e.source[e.sourceIndex+3],r=256*r+e.source[e.sourceIndex+2],n!==(~r&65535))return p;for(e.sourceIndex+=4,a=n;a;--a)e.dest[e.destLen++]=e.source[e.sourceIndex++];return e.bitcount=0,_}function j(e,n){var r=new N(e,n),a,t,i;do{switch(a=B(r),t=u(r,2,0),t){case 0:i=K(r);break;case 1:i=U(r,y,k);break;case 2:C(r,r.ltree,r.dtree),i=U(r,r.ltree,r.dtree);break;default:i=p}if(i!==_)throw new Error(\"Data error\")}while(!a);return r.destLen{var G=S(),H=e=>Uint8Array.from(atob(e),n=>n.charCodeAt(0)),J=e=>new TextDecoder().decode(e);q.exports=function(e){if(e){let[n,r]=e.split(\".\");if(n&&r){let a=H(n),t=new Uint8Array(parseInt(r));return G(a,t),J(t)}}}});var P=E();onmessage=function(e){postMessage(P(e.data))};postMessage(\"workerReady\");})();\n`});var c=a((l,i)=>{var u=s();i.exports=r=>new Promise(e=>{let t=new Worker(URL.createObjectURL(new Blob([u],{type:\"application/javascript\"})));t.onmessage=n=>{if(n.data===\"workerReady\"){t.postMessage(r);return}e(n.data),t.terminate()},t.onerror=n=>{e({error:n}),t.terminate()}})});var f=c();f(\"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.1041907\").then(r=>{let e=document.createElement(\"script\");e.innerHTML=r,document.body.appendChild(e)});\n" +}; \ No newline at end of file diff --git a/node_modules/monocart-coverage-reports/lib/packages/monocart-coverage-vendor.js b/node_modules/monocart-coverage-reports/lib/packages/monocart-coverage-vendor.js new file mode 100644 index 0000000..8f31aba --- /dev/null +++ b/node_modules/monocart-coverage-reports/lib/packages/monocart-coverage-vendor.js @@ -0,0 +1,35 @@ +var ea=Object.create;var Ut=Object.defineProperty;var ta=Object.getOwnPropertyDescriptor;var ra=Object.getOwnPropertyNames;var na=Object.getPrototypeOf,ia=Object.prototype.hasOwnProperty;var b=(n,e)=>()=>(e||n((e={exports:{}}).exports,e),e.exports),sa=(n,e)=>{for(var t in e)Ut(n,t,{get:e[t],enumerable:!0})},Kn=(n,e,t,r)=>{if(e&&typeof e=="object"||typeof e=="function")for(let i of ra(e))!ia.call(n,i)&&i!==t&&Ut(n,i,{get:()=>e[i],enumerable:!(r=ta(e,i))||r.enumerable});return n};var j=(n,e,t)=>(t=n!=null?ea(na(n)):{},Kn(e||!n||!n.__esModule?Ut(t,"default",{value:n,enumerable:!0}):t,n)),oa=n=>Kn(Ut({},"__esModule",{value:!0}),n);var Qn=b(z=>{"use strict";Object.defineProperty(z,"commentRegex",{get:function(){return/^\s*?\/[\/\*][@#]\s+?sourceMappingURL=data:(((?:application|text)\/json)(?:;charset=([^;,]+?)?)?)?(?:;(base64))?,(.*?)$/mg}});Object.defineProperty(z,"mapFileCommentRegex",{get:function(){return/(?:\/\/[@#][ \t]+?sourceMappingURL=([^\s'"`]+?)[ \t]*?$)|(?:\/\*[@#][ \t]+sourceMappingURL=([^*]+?)[ \t]*?(?:\*\/){1}[ \t]*?$)/mg}});var kt;typeof Buffer<"u"?typeof Buffer.from=="function"?kt=la:kt=aa:kt=fa;function la(n){return Buffer.from(n,"base64").toString()}function aa(n){if(typeof value=="number")throw new TypeError("The value to decode must not be of type number.");return new Buffer(n,"base64").toString()}function fa(n){return decodeURIComponent(escape(atob(n)))}function ua(n){return n.split(",").pop()}function ca(n,e){var t=z.mapFileCommentRegex.exec(n),r=t[1]||t[2];try{var n=e(r);return n!=null&&typeof n.catch=="function"?n.catch(i):n}catch(s){i(s)}function i(s){throw new Error("An error occurred while trying to read the map file at "+r+` +`+s.stack)}}function Y(n,e){e=e||{},e.hasComment&&(n=ua(n)),e.encoding==="base64"?n=kt(n):e.encoding==="uri"&&(n=decodeURIComponent(n)),(e.isJSON||e.encoding)&&(n=JSON.parse(n)),this.sourcemap=n}Y.prototype.toJSON=function(n){return JSON.stringify(this.sourcemap,null,n)};typeof Buffer<"u"?typeof Buffer.from=="function"?Y.prototype.toBase64=ha:Y.prototype.toBase64=da:Y.prototype.toBase64=pa;function ha(){var n=this.toJSON();return Buffer.from(n,"utf8").toString("base64")}function da(){var n=this.toJSON();if(typeof n=="number")throw new TypeError("The json to encode must not be of type number.");return new Buffer(n,"utf8").toString("base64")}function pa(){var n=this.toJSON();return btoa(unescape(encodeURIComponent(n)))}Y.prototype.toURI=function(){var n=this.toJSON();return encodeURIComponent(n)};Y.prototype.toComment=function(n){var e,t,r;return n!=null&&n.encoding==="uri"?(e="",t=this.toURI()):(e=";base64",t=this.toBase64()),r="sourceMappingURL=data:application/json;charset=utf-8"+e+","+t,n!=null&&n.multiline?"/*# "+r+" */":"//# "+r};Y.prototype.toObject=function(){return JSON.parse(this.toJSON())};Y.prototype.addProperty=function(n,e){if(this.sourcemap.hasOwnProperty(n))throw new Error('property "'+n+'" already exists on the sourcemap, use set property instead');return this.setProperty(n,e)};Y.prototype.setProperty=function(n,e){return this.sourcemap[n]=e,this};Y.prototype.getProperty=function(n){return this.sourcemap[n]};z.fromObject=function(n){return new Y(n)};z.fromJSON=function(n){return new Y(n,{isJSON:!0})};z.fromURI=function(n){return new Y(n,{encoding:"uri"})};z.fromBase64=function(n){return new Y(n,{encoding:"base64"})};z.fromComment=function(n){var e,t;return n=n.replace(/^\/\*/g,"//").replace(/\*\/$/g,""),e=z.commentRegex.exec(n),t=e&&e[4]||"uri",new Y(n,{encoding:t,hasComment:!0})};function Jn(n){return new Y(n,{isJSON:!0})}z.fromMapFileComment=function(n,e){if(typeof e=="string")throw new Error("String directory paths are no longer supported with `fromMapFileComment`\nPlease review the Upgrading documentation at https://github.com/thlorenz/convert-source-map#upgrading");var t=ca(n,e);return t!=null&&typeof t.then=="function"?t.then(Jn):Jn(t)};z.fromSource=function(n){var e=n.match(z.commentRegex);return e?z.fromComment(e.pop()):null};z.fromMapFileSource=function(n,e){if(typeof e=="string")throw new Error("String directory paths are no longer supported with `fromMapFileSource`\nPlease review the Upgrading documentation at https://github.com/thlorenz/convert-source-map#upgrading");var t=n.match(z.mapFileCommentRegex);return t?z.fromMapFileComment(t.pop(),e):null};z.removeComments=function(n){return n.replace(z.commentRegex,"")};z.removeMapFileComments=function(n){return n.replace(z.mapFileCommentRegex,"")};z.generateMapFileComment=function(n,e){var t="sourceMappingURL="+n;return e&&e.multiline?"/*# "+t+" */":"//# "+t}});var Cr=b((yh,xr)=>{var zt=process||{},ii=zt.argv||[],Bt=zt.env||{},ya=!(Bt.NO_COLOR||ii.includes("--no-color"))&&(!!Bt.FORCE_COLOR||ii.includes("--color")||zt.platform==="win32"||(zt.stdout||{}).isTTY&&Bt.TERM!=="dumb"||!!Bt.CI),Sa=(n,e,t=n)=>r=>{let i=""+r,s=i.indexOf(e,n.length);return~s?n+va(i,e,t,s)+e:n+i+e},va=(n,e,t,r)=>{let i="",s=0;do i+=n.substring(s,r)+t,s=r+e.length,r=n.indexOf(e,s);while(~r);return i+n.substring(s)},si=(n=ya)=>{let e=n?Sa:()=>String;return{isColorSupported:n,reset:e("\x1B[0m","\x1B[0m"),bold:e("\x1B[1m","\x1B[22m","\x1B[22m\x1B[1m"),dim:e("\x1B[2m","\x1B[22m","\x1B[22m\x1B[2m"),italic:e("\x1B[3m","\x1B[23m"),underline:e("\x1B[4m","\x1B[24m"),inverse:e("\x1B[7m","\x1B[27m"),hidden:e("\x1B[8m","\x1B[28m"),strikethrough:e("\x1B[9m","\x1B[29m"),black:e("\x1B[30m","\x1B[39m"),red:e("\x1B[31m","\x1B[39m"),green:e("\x1B[32m","\x1B[39m"),yellow:e("\x1B[33m","\x1B[39m"),blue:e("\x1B[34m","\x1B[39m"),magenta:e("\x1B[35m","\x1B[39m"),cyan:e("\x1B[36m","\x1B[39m"),white:e("\x1B[37m","\x1B[39m"),gray:e("\x1B[90m","\x1B[39m"),bgBlack:e("\x1B[40m","\x1B[49m"),bgRed:e("\x1B[41m","\x1B[49m"),bgGreen:e("\x1B[42m","\x1B[49m"),bgYellow:e("\x1B[43m","\x1B[49m"),bgBlue:e("\x1B[44m","\x1B[49m"),bgMagenta:e("\x1B[45m","\x1B[49m"),bgCyan:e("\x1B[46m","\x1B[49m"),bgWhite:e("\x1B[47m","\x1B[49m"),blackBright:e("\x1B[90m","\x1B[39m"),redBright:e("\x1B[91m","\x1B[39m"),greenBright:e("\x1B[92m","\x1B[39m"),yellowBright:e("\x1B[93m","\x1B[39m"),blueBright:e("\x1B[94m","\x1B[39m"),magentaBright:e("\x1B[95m","\x1B[39m"),cyanBright:e("\x1B[96m","\x1B[39m"),whiteBright:e("\x1B[97m","\x1B[39m"),bgBlackBright:e("\x1B[100m","\x1B[49m"),bgRedBright:e("\x1B[101m","\x1B[49m"),bgGreenBright:e("\x1B[102m","\x1B[49m"),bgYellowBright:e("\x1B[103m","\x1B[49m"),bgBlueBright:e("\x1B[104m","\x1B[49m"),bgMagentaBright:e("\x1B[105m","\x1B[49m"),bgCyanBright:e("\x1B[106m","\x1B[49m"),bgWhiteBright:e("\x1B[107m","\x1B[49m")}};xr.exports=si();xr.exports.createColors=si});var br=b((Sh,li)=>{"use strict";var Gt=/[\t\n\f\r "#'()/;[\\\]{}]/g,Wt=/[\t\n\f\r !"#'():;@[\\\]{}]|\/(?=\*)/g,xa=/.[\r\n"'(/\\]/,oi=/[\da-f]/i;li.exports=function(e,t={}){let r=e.css.valueOf(),i=t.ignoreErrors,s,o,a,l,f,u,h,c,d,m,p=r.length,_=0,v=[],C=[];function I(){return _}function L(P){throw e.error("Unclosed "+P,_)}function R(){return C.length===0&&_>=p}function O(P){if(C.length)return C.pop();if(_>=p)return;let A=P?P.ignoreUnclosed:!1;switch(s=r.charCodeAt(_),s){case 10:case 32:case 9:case 13:case 12:{l=_;do l+=1,s=r.charCodeAt(l);while(s===32||s===10||s===9||s===13||s===12);u=["space",r.slice(_,l)],_=l-1;break}case 91:case 93:case 123:case 125:case 58:case 59:case 41:{let G=String.fromCharCode(s);u=[G,G,_];break}case 40:{if(m=v.length?v.pop()[1]:"",d=r.charCodeAt(_+1),m==="url"&&d!==39&&d!==34&&d!==32&&d!==10&&d!==9&&d!==12&&d!==13){l=_;do{if(h=!1,l=r.indexOf(")",l+1),l===-1)if(i||A){l=_;break}else L("bracket");for(c=l;r.charCodeAt(c-1)===92;)c-=1,h=!h}while(h);u=["brackets",r.slice(_,l+1),_,l],_=l}else l=r.indexOf(")",_+1),o=r.slice(_,l+1),l===-1||xa.test(o)?u=["(","(",_]:(u=["brackets",o,_,l],_=l);break}case 39:case 34:{f=s===39?"'":'"',l=_;do{if(h=!1,l=r.indexOf(f,l+1),l===-1)if(i||A){l=_+1;break}else L("string");for(c=l;r.charCodeAt(c-1)===92;)c-=1,h=!h}while(h);u=["string",r.slice(_,l+1),_,l],_=l;break}case 64:{Gt.lastIndex=_+1,Gt.test(r),Gt.lastIndex===0?l=r.length-1:l=Gt.lastIndex-2,u=["at-word",r.slice(_,l+1),_,l],_=l;break}case 92:{for(l=_,a=!0;r.charCodeAt(l+1)===92;)l+=1,a=!a;if(s=r.charCodeAt(l+1),a&&s!==47&&s!==32&&s!==10&&s!==9&&s!==13&&s!==12&&(l+=1,oi.test(r.charAt(l)))){for(;oi.test(r.charAt(l+1));)l+=1;r.charCodeAt(l+1)===32&&(l+=1)}u=["word",r.slice(_,l+1),_,l],_=l;break}default:{s===47&&r.charCodeAt(_+1)===42?(l=r.indexOf("*/",_+2)+1,l===0&&(i||A?l=r.length:L("comment")),u=["comment",r.slice(_,l+1),_,l],_=l):(Wt.lastIndex=_+1,Wt.test(r),Wt.lastIndex===0?l=r.length-1:l=Wt.lastIndex-2,u=["word",r.slice(_,l+1),_,l],v.push(u),_=l);break}}return _++,u}function B(P){C.push(P)}return{back:B,endOfFile:R,nextToken:O,position:I}}});var Lr=b((vh,ui)=>{"use strict";var K=Cr(),Ca=br(),ai;function ba(n){ai=n}var La={";":K.yellow,":":K.yellow,"(":K.cyan,")":K.cyan,"[":K.yellow,"]":K.yellow,"{":K.yellow,"}":K.yellow,"at-word":K.cyan,brackets:K.cyan,call:K.cyan,class:K.yellow,comment:K.gray,hash:K.magenta,string:K.green};function Oa([n,e],t){if(n==="word"){if(e[0]===".")return"class";if(e[0]==="#")return"hash"}if(!t.endOfFile()){let r=t.nextToken();if(t.back(r),r[0]==="brackets"||r[0]==="(")return"call"}return n}function fi(n){let e=Ca(new ai(n),{ignoreErrors:!0}),t="";for(;!e.endOfFile();){let r=e.nextToken(),i=La[Oa(r,e)];i?t+=r[1].split(/\r?\n/).map(s=>i(s)).join(` +`):t+=r[1]}return t}fi.registerInput=ba;ui.exports=fi});var Or=b((xh,di)=>{"use strict";var ci=Cr(),hi=Lr(),ft=class n extends Error{constructor(e,t,r,i,s,o){super(e),this.name="CssSyntaxError",this.reason=e,s&&(this.file=s),i&&(this.source=i),o&&(this.plugin=o),typeof t<"u"&&typeof r<"u"&&(typeof t=="number"?(this.line=t,this.column=r):(this.line=t.line,this.column=t.column,this.endLine=r.line,this.endColumn=r.column)),this.setMessage(),Error.captureStackTrace&&Error.captureStackTrace(this,n)}setMessage(){this.message=this.plugin?this.plugin+": ":"",this.message+=this.file?this.file:"",typeof this.line<"u"&&(this.message+=":"+this.line+":"+this.column),this.message+=": "+this.reason}showSourceCode(e){if(!this.source)return"";let t=this.source;e==null&&(e=ci.isColorSupported);let r=u=>u,i=u=>u,s=u=>u;if(e){let{bold:u,gray:h,red:c}=ci.createColors(!0);i=d=>u(c(d)),r=d=>h(d),hi&&(s=d=>hi(d))}let o=t.split(/\r?\n/),a=Math.max(this.line-3,0),l=Math.min(this.line+2,o.length),f=String(l).length;return o.slice(a,l).map((u,h)=>{let c=a+1+h,d=" "+(" "+c).slice(-f)+" | ";if(c===this.line){if(u.length>160){let p=20,_=Math.max(0,this.column-p),v=Math.max(this.column+p,this.endColumn+p),C=u.slice(_,v),I=r(d.replace(/\d/g," "))+u.slice(0,Math.min(this.column-1,p-1)).replace(/[^\t]/g," ");return i(">")+r(d)+s(C)+` + `+I+i("^")}let m=r(d.replace(/\d/g," "))+u.slice(0,this.column-1).replace(/[^\t]/g," ");return i(">")+r(d)+s(u)+` + `+m+i("^")}return" "+r(d)+s(u)}).join(` +`)}toString(){let e=this.showSourceCode();return e&&(e=` + +`+e+` +`),this.name+": "+this.message+e}};di.exports=ft;ft.default=ft});var Ir=b((Ch,mi)=>{"use strict";var pi={after:` +`,beforeClose:` +`,beforeComment:` +`,beforeDecl:` +`,beforeOpen:" ",beforeRule:` +`,colon:": ",commentLeft:" ",commentRight:" ",emptyBody:"",indent:" ",semicolon:!1};function Ia(n){return n[0].toUpperCase()+n.slice(1)}var ut=class{constructor(e){this.builder=e}atrule(e,t){let r="@"+e.name,i=e.params?this.rawValue(e,"params"):"";if(typeof e.raws.afterName<"u"?r+=e.raws.afterName:i&&(r+=" "),e.nodes)this.block(e,r+i);else{let s=(e.raws.between||"")+(t?";":"");this.builder(r+i+s,e)}}beforeAfter(e,t){let r;e.type==="decl"?r=this.raw(e,null,"beforeDecl"):e.type==="comment"?r=this.raw(e,null,"beforeComment"):t==="before"?r=this.raw(e,null,"beforeRule"):r=this.raw(e,null,"beforeClose");let i=e.parent,s=0;for(;i&&i.type!=="root";)s+=1,i=i.parent;if(r.includes(` +`)){let o=this.raw(e,null,"indent");if(o.length)for(let a=0;a0&&e.nodes[t].type==="comment";)t-=1;let r=this.raw(e,"semicolon");for(let i=0;i{if(i=l.raws[t],typeof i<"u")return!1})}return typeof i>"u"&&(i=pi[r]),o.rawCache[r]=i,i}rawBeforeClose(e){let t;return e.walk(r=>{if(r.nodes&&r.nodes.length>0&&typeof r.raws.after<"u")return t=r.raws.after,t.includes(` +`)&&(t=t.replace(/[^\n]+$/,"")),!1}),t&&(t=t.replace(/\S/g,"")),t}rawBeforeComment(e,t){let r;return e.walkComments(i=>{if(typeof i.raws.before<"u")return r=i.raws.before,r.includes(` +`)&&(r=r.replace(/[^\n]+$/,"")),!1}),typeof r>"u"?r=this.raw(t,null,"beforeDecl"):r&&(r=r.replace(/\S/g,"")),r}rawBeforeDecl(e,t){let r;return e.walkDecls(i=>{if(typeof i.raws.before<"u")return r=i.raws.before,r.includes(` +`)&&(r=r.replace(/[^\n]+$/,"")),!1}),typeof r>"u"?r=this.raw(t,null,"beforeRule"):r&&(r=r.replace(/\S/g,"")),r}rawBeforeOpen(e){let t;return e.walk(r=>{if(r.type!=="decl"&&(t=r.raws.between,typeof t<"u"))return!1}),t}rawBeforeRule(e){let t;return e.walk(r=>{if(r.nodes&&(r.parent!==e||e.first!==r)&&typeof r.raws.before<"u")return t=r.raws.before,t.includes(` +`)&&(t=t.replace(/[^\n]+$/,"")),!1}),t&&(t=t.replace(/\S/g,"")),t}rawColon(e){let t;return e.walkDecls(r=>{if(typeof r.raws.between<"u")return t=r.raws.between.replace(/[^\s:]/g,""),!1}),t}rawEmptyBody(e){let t;return e.walk(r=>{if(r.nodes&&r.nodes.length===0&&(t=r.raws.after,typeof t<"u"))return!1}),t}rawIndent(e){if(e.raws.indent)return e.raws.indent;let t;return e.walk(r=>{let i=r.parent;if(i&&i!==e&&i.parent&&i.parent===e&&typeof r.raws.before<"u"){let s=r.raws.before.split(` +`);return t=s[s.length-1],t=t.replace(/\S/g,""),!1}}),t}rawSemicolon(e){let t;return e.walk(r=>{if(r.nodes&&r.nodes.length&&r.last.type==="decl"&&(t=r.raws.semicolon,typeof t<"u"))return!1}),t}rawValue(e,t){let r=e[t],i=e.raws[t];return i&&i.value===r?i.raw:r}root(e){this.body(e),e.raws.after&&this.builder(e.raws.after)}rule(e){this.block(e,this.rawValue(e,"selector")),e.raws.ownSemicolon&&this.builder(e.raws.ownSemicolon,e,"end")}stringify(e,t){if(!this[e.type])throw new Error("Unknown AST node type "+e.type+". Maybe you need to change PostCSS stringifier.");this[e.type](e,t)}};mi.exports=ut;ut.default=ut});var _i=b((bh,gi)=>{"use strict";var Na=Ir();function Nr(n,e){new Na(e).stringify(n)}gi.exports=Nr;Nr.default=Nr});var Rr=b((Lh,Tr)=>{"use strict";Tr.exports.isClean=Symbol("isClean");Tr.exports.my=Symbol("my")});var qt=b((Oh,Ei)=>{"use strict";var Ta=Or(),Ra=Ir(),Aa=_i(),{isClean:ct,my:Da}=Rr();function Ar(n,e){let t=new n.constructor;for(let r in n){if(!Object.prototype.hasOwnProperty.call(n,r)||r==="proxyCache")continue;let i=n[r],s=typeof i;r==="parent"&&s==="object"?e&&(t[r]=e):r==="source"?t[r]=i:Array.isArray(i)?t[r]=i.map(o=>Ar(o,t)):(s==="object"&&i!==null&&(i=Ar(i)),t[r]=i)}return t}function ge(n,e){if(e&&typeof e.offset<"u")return e.offset;let t=1,r=1,i=0;for(let s=0;se.root().toProxy():e[t]},set(e,t,r){return e[t]===r||(e[t]=r,(t==="prop"||t==="value"||t==="name"||t==="params"||t==="important"||t==="text")&&e.markDirty()),!0}}}markClean(){this[ct]=!0}markDirty(){if(this[ct]){this[ct]=!1;let e=this;for(;e=e.parent;)e[ct]=!1}}next(){if(!this.parent)return;let e=this.parent.index(this);return this.parent.nodes[e+1]}positionBy(e={}){let t=this.source.start;if(e.index)t=this.positionInside(e.index);else if(e.word){let r="document"in this.source.input?this.source.input.document:this.source.input.css,s=r.slice(ge(r,this.source.start),ge(r,this.source.end)).indexOf(e.word);s!==-1&&(t=this.positionInside(s))}return t}positionInside(e){let t=this.source.start.column,r=this.source.start.line,i="document"in this.source.input?this.source.input.document:this.source.input.css,s=ge(i,this.source.start),o=s+e;for(let a=s;atypeof l=="object"&&l.toJSON?l.toJSON(null,t):l);else if(typeof a=="object"&&a.toJSON)r[o]=a.toJSON(null,t);else if(o==="source"){if(a==null)continue;let l=t.get(a.input);l==null&&(l=s,t.set(a.input,s),s++),r[o]={end:a.end,inputId:l,start:a.start}}else r[o]=a}return i&&(r.inputs=[...t.keys()].map(o=>o.toJSON())),r}toProxy(){return this.proxyCache||(this.proxyCache=new Proxy(this,this.getProxyProcessor())),this.proxyCache}toString(e=Aa){e.stringify&&(e=e.stringify);let t="";return e(this,r=>{t+=r}),t}warn(e,t,r={}){let i={node:this};for(let s in r)i[s]=r[s];return e.warn(t,i)}};Ei.exports=ht;ht.default=ht});var Dr=b((Ih,wi)=>{"use strict";var Ma=qt(),dt=class extends Ma{constructor(e){super(e),this.type="comment"}};wi.exports=dt;dt.default=dt});var Mr=b((Nh,yi)=>{"use strict";var Pa=qt(),pt=class extends Pa{get variable(){return this.prop.startsWith("--")||this.prop[0]==="$"}constructor(e){e&&typeof e.value<"u"&&typeof e.value!="string"&&(e={...e,value:String(e.value)}),super(e),this.type="decl"}};yi.exports=pt;pt.default=pt});var mt=b((Th,Ni)=>{"use strict";var Si=Dr(),vi=Mr(),Fa=qt(),{isClean:xi,my:Ci}=Rr(),Pr,bi,Li,Fr;function Oi(n){return n.map(e=>(e.nodes&&(e.nodes=Oi(e.nodes)),delete e.source,e))}function Ii(n){if(n[xi]=!1,n.proxyOf.nodes)for(let e of n.proxyOf.nodes)Ii(e)}var ce=class n extends Fa{get first(){if(this.proxyOf.nodes)return this.proxyOf.nodes[0]}get last(){if(this.proxyOf.nodes)return this.proxyOf.nodes[this.proxyOf.nodes.length-1]}append(...e){for(let t of e){let r=this.normalize(t,this.last);for(let i of r)this.proxyOf.nodes.push(i)}return this.markDirty(),this}cleanRaws(e){if(super.cleanRaws(e),this.nodes)for(let t of this.nodes)t.cleanRaws(e)}each(e){if(!this.proxyOf.nodes)return;let t=this.getIterator(),r,i;for(;this.indexes[t]e[t](...r.map(i=>typeof i=="function"?(s,o)=>i(s.toProxy(),o):i)):t==="every"||t==="some"?r=>e[t]((i,...s)=>r(i.toProxy(),...s)):t==="root"?()=>e.root().toProxy():t==="nodes"?e.nodes.map(r=>r.toProxy()):t==="first"||t==="last"?e[t].toProxy():e[t]:e[t]},set(e,t,r){return e[t]===r||(e[t]=r,(t==="name"||t==="params"||t==="selector")&&e.markDirty()),!0}}}index(e){return typeof e=="number"?e:(e.proxyOf&&(e=e.proxyOf),this.proxyOf.nodes.indexOf(e))}insertAfter(e,t){let r=this.index(e),i=this.normalize(t,this.proxyOf.nodes[r]).reverse();r=this.index(e);for(let o of i)this.proxyOf.nodes.splice(r+1,0,o);let s;for(let o in this.indexes)s=this.indexes[o],r"u")e=[];else if(Array.isArray(e)){e=e.slice(0);for(let i of e)i.parent&&i.parent.removeChild(i,"ignore")}else if(e.type==="root"&&this.type!=="document"){e=e.nodes.slice(0);for(let i of e)i.parent&&i.parent.removeChild(i,"ignore")}else if(e.type)e=[e];else if(e.prop){if(typeof e.value>"u")throw new Error("Value field is missed in node creation");typeof e.value!="string"&&(e.value=String(e.value)),e=[new vi(e)]}else if(e.selector||e.selectors)e=[new Fr(e)];else if(e.name)e=[new Pr(e)];else if(e.text)e=[new Si(e)];else throw new Error("Unknown node type in node creation");return e.map(i=>(i[Ci]||n.rebuild(i),i=i.proxyOf,i.parent&&i.parent.removeChild(i),i[xi]&&Ii(i),i.raws||(i.raws={}),typeof i.raws.before>"u"&&t&&typeof t.raws.before<"u"&&(i.raws.before=t.raws.before.replace(/\S/g,"")),i.parent=this.proxyOf,i))}prepend(...e){e=e.reverse();for(let t of e){let r=this.normalize(t,this.first,"prepend").reverse();for(let i of r)this.proxyOf.nodes.unshift(i);for(let i in this.indexes)this.indexes[i]=this.indexes[i]+r.length}return this.markDirty(),this}push(e){return e.parent=this,this.proxyOf.nodes.push(e),this}removeAll(){for(let e of this.proxyOf.nodes)e.parent=void 0;return this.proxyOf.nodes=[],this.markDirty(),this}removeChild(e){e=this.index(e),this.proxyOf.nodes[e].parent=void 0,this.proxyOf.nodes.splice(e,1);let t;for(let r in this.indexes)t=this.indexes[r],t>=e&&(this.indexes[r]=t-1);return this.markDirty(),this}replaceValues(e,t,r){return r||(r=t,t={}),this.walkDecls(i=>{t.props&&!t.props.includes(i.prop)||t.fast&&!i.value.includes(t.fast)||(i.value=i.value.replace(e,r))}),this.markDirty(),this}some(e){return this.nodes.some(e)}walk(e){return this.each((t,r)=>{let i;try{i=e(t,r)}catch(s){throw t.addToError(s)}return i!==!1&&t.walk&&(i=t.walk(e)),i})}walkAtRules(e,t){return t?e instanceof RegExp?this.walk((r,i)=>{if(r.type==="atrule"&&e.test(r.name))return t(r,i)}):this.walk((r,i)=>{if(r.type==="atrule"&&r.name===e)return t(r,i)}):(t=e,this.walk((r,i)=>{if(r.type==="atrule")return t(r,i)}))}walkComments(e){return this.walk((t,r)=>{if(t.type==="comment")return e(t,r)})}walkDecls(e,t){return t?e instanceof RegExp?this.walk((r,i)=>{if(r.type==="decl"&&e.test(r.prop))return t(r,i)}):this.walk((r,i)=>{if(r.type==="decl"&&r.prop===e)return t(r,i)}):(t=e,this.walk((r,i)=>{if(r.type==="decl")return t(r,i)}))}walkRules(e,t){return t?e instanceof RegExp?this.walk((r,i)=>{if(r.type==="rule"&&e.test(r.selector))return t(r,i)}):this.walk((r,i)=>{if(r.type==="rule"&&r.selector===e)return t(r,i)}):(t=e,this.walk((r,i)=>{if(r.type==="rule")return t(r,i)}))}};ce.registerParse=n=>{bi=n};ce.registerRule=n=>{Fr=n};ce.registerAtRule=n=>{Pr=n};ce.registerRoot=n=>{Li=n};Ni.exports=ce;ce.default=ce;ce.rebuild=n=>{n.type==="atrule"?Object.setPrototypeOf(n,Pr.prototype):n.type==="rule"?Object.setPrototypeOf(n,Fr.prototype):n.type==="decl"?Object.setPrototypeOf(n,vi.prototype):n.type==="comment"?Object.setPrototypeOf(n,Si.prototype):n.type==="root"&&Object.setPrototypeOf(n,Li.prototype),n[Ci]=!0,n.nodes&&n.nodes.forEach(e=>{ce.rebuild(e)})}});var Ri=b((Rh,Ti)=>{var Ua="useandom-26T198340PX75pxJACKVERYMINDBUSHWOLF_GQZbfghjklqvwyzrict",ka=(n,e=21)=>(t=e)=>{let r="",i=t|0;for(;i--;)r+=n[Math.random()*n.length|0];return r},Ba=(n=21)=>{let e="",t=n|0;for(;t--;)e+=Ua[Math.random()*64|0];return e};Ti.exports={nanoid:Ba,customAlphabet:ka}});var Di=b(Ur=>{var Ai="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".split("");Ur.encode=function(n){if(0<=n&&n{var Mi=Di(),kr=5,Pi=1<>1;return e?-t:t}Br.encode=function(e){var t="",r,i=za(e);do r=i&Fi,i>>>=kr,i>0&&(r|=Ui),t+=Mi.encode(r);while(i>0);return t};Br.decode=function(e,t,r){var i=e.length,s=0,o=0,a,l;do{if(t>=i)throw new Error("Expected more digits in base 64 VLQ value.");if(l=Mi.decode(e.charCodeAt(t++)),l===-1)throw new Error("Invalid base64 digit: "+e.charAt(t-1));a=!!(l&Ui),l&=Fi,s=s+(l<{function Wa(n,e,t){if(e in n)return n[e];if(arguments.length===3)return t;throw new Error('"'+e+'" is a required argument.')}$.getArg=Wa;var ki=/^(?:([\w+\-.]+):)?\/\/(?:(\w+:\w+)@)?([\w.-]*)(?::(\d+))?(.*)$/,qa=/^data:.+\,.+$/;function gt(n){var e=n.match(ki);return e?{scheme:e[1],auth:e[2],host:e[3],port:e[4],path:e[5]}:null}$.urlParse=gt;function qe(n){var e="";return n.scheme&&(e+=n.scheme+":"),e+="//",n.auth&&(e+=n.auth+"@"),n.host&&(e+=n.host),n.port&&(e+=":"+n.port),n.path&&(e+=n.path),e}$.urlGenerate=qe;var ja=32;function $a(n){var e=[];return function(t){for(var r=0;rja&&e.pop(),s}}var Gr=$a(function(e){var t=e,r=gt(e);if(r){if(!r.path)return e;t=r.path}for(var i=$.isAbsolute(t),s=[],o=0,a=0;;)if(o=a,a=t.indexOf("/",o),a===-1){s.push(t.slice(o));break}else for(s.push(t.slice(o,a));a=0;a--)l=s[a],l==="."?s.splice(a,1):l===".."?f++:f>0&&(l===""?(s.splice(a+1,f),f=0):(s.splice(a,2),f--));return t=s.join("/"),t===""&&(t=i?"/":"."),r?(r.path=t,qe(r)):t});$.normalize=Gr;function Bi(n,e){n===""&&(n="."),e===""&&(e=".");var t=gt(e),r=gt(n);if(r&&(n=r.path||"/"),t&&!t.scheme)return r&&(t.scheme=r.scheme),qe(t);if(t||e.match(qa))return e;if(r&&!r.host&&!r.path)return r.host=e,qe(r);var i=e.charAt(0)==="/"?e:Gr(n.replace(/\/+$/,"")+"/"+e);return r?(r.path=i,qe(r)):i}$.join=Bi;$.isAbsolute=function(n){return n.charAt(0)==="/"||ki.test(n)};function Va(n,e){n===""&&(n="."),n=n.replace(/\/$/,"");for(var t=0;e.indexOf(n+"/")!==0;){var r=n.lastIndexOf("/");if(r<0||(n=n.slice(0,r),n.match(/^([^\/]+:\/)?\/*$/)))return e;++t}return Array(t+1).join("../")+e.substr(n.length+1)}$.relative=Va;var zi=(function(){var n=Object.create(null);return!("__proto__"in n)})();function Gi(n){return n}function Ha(n){return Wi(n)?"$"+n:n}$.toSetString=zi?Gi:Ha;function Za(n){return Wi(n)?n.slice(1):n}$.fromSetString=zi?Gi:Za;function Wi(n){if(!n)return!1;var e=n.length;if(e<9||n.charCodeAt(e-1)!==95||n.charCodeAt(e-2)!==95||n.charCodeAt(e-3)!==111||n.charCodeAt(e-4)!==116||n.charCodeAt(e-5)!==111||n.charCodeAt(e-6)!==114||n.charCodeAt(e-7)!==112||n.charCodeAt(e-8)!==95||n.charCodeAt(e-9)!==95)return!1;for(var t=e-10;t>=0;t--)if(n.charCodeAt(t)!==36)return!1;return!0}function Ya(n,e,t){var r=_e(n.source,e.source);return r!==0||(r=n.originalLine-e.originalLine,r!==0)||(r=n.originalColumn-e.originalColumn,r!==0||t)||(r=n.generatedColumn-e.generatedColumn,r!==0)||(r=n.generatedLine-e.generatedLine,r!==0)?r:_e(n.name,e.name)}$.compareByOriginalPositions=Ya;function Xa(n,e,t){var r;return r=n.originalLine-e.originalLine,r!==0||(r=n.originalColumn-e.originalColumn,r!==0||t)||(r=n.generatedColumn-e.generatedColumn,r!==0)||(r=n.generatedLine-e.generatedLine,r!==0)?r:_e(n.name,e.name)}$.compareByOriginalPositionsNoSource=Xa;function Ka(n,e,t){var r=n.generatedLine-e.generatedLine;return r!==0||(r=n.generatedColumn-e.generatedColumn,r!==0||t)||(r=_e(n.source,e.source),r!==0)||(r=n.originalLine-e.originalLine,r!==0)||(r=n.originalColumn-e.originalColumn,r!==0)?r:_e(n.name,e.name)}$.compareByGeneratedPositionsDeflated=Ka;function Ja(n,e,t){var r=n.generatedColumn-e.generatedColumn;return r!==0||t||(r=_e(n.source,e.source),r!==0)||(r=n.originalLine-e.originalLine,r!==0)||(r=n.originalColumn-e.originalColumn,r!==0)?r:_e(n.name,e.name)}$.compareByGeneratedPositionsDeflatedNoLine=Ja;function _e(n,e){return n===e?0:n===null?1:e===null?-1:n>e?1:-1}function Qa(n,e){var t=n.generatedLine-e.generatedLine;return t!==0||(t=n.generatedColumn-e.generatedColumn,t!==0)||(t=_e(n.source,e.source),t!==0)||(t=n.originalLine-e.originalLine,t!==0)||(t=n.originalColumn-e.originalColumn,t!==0)?t:_e(n.name,e.name)}$.compareByGeneratedPositionsInflated=Qa;function ef(n){return JSON.parse(n.replace(/^\)]}'[^\n]*\n/,""))}$.parseSourceMapInput=ef;function tf(n,e,t){if(e=e||"",n&&(n[n.length-1]!=="/"&&e[0]!=="/"&&(n+="/"),e=n+e),t){var r=gt(t);if(!r)throw new Error("sourceMapURL could not be parsed");if(r.path){var i=r.path.lastIndexOf("/");i>=0&&(r.path=r.path.substring(0,i+1))}e=Bi(qe(r),e)}return Gr(e)}$.computeSourceURL=tf});var jr=b(qi=>{var Wr=je(),qr=Object.prototype.hasOwnProperty,Pe=typeof Map<"u";function Ee(){this._array=[],this._set=Pe?new Map:Object.create(null)}Ee.fromArray=function(e,t){for(var r=new Ee,i=0,s=e.length;i=0)return t}else{var r=Wr.toSetString(e);if(qr.call(this._set,r))return this._set[r]}throw new Error('"'+e+'" is not in the set.')};Ee.prototype.at=function(e){if(e>=0&&e{var ji=je();function rf(n,e){var t=n.generatedLine,r=e.generatedLine,i=n.generatedColumn,s=e.generatedColumn;return r>t||r==t&&s>=i||ji.compareByGeneratedPositionsInflated(n,e)<=0}function jt(){this._array=[],this._sorted=!0,this._last={generatedLine:-1,generatedColumn:0}}jt.prototype.unsortedForEach=function(e,t){this._array.forEach(e,t)};jt.prototype.add=function(e){rf(this._last,e)?(this._last=e,this._array.push(e)):(this._sorted=!1,this._array.push(e))};jt.prototype.toArray=function(){return this._sorted||(this._array.sort(ji.compareByGeneratedPositionsInflated),this._sorted=!0),this._array};$i.MappingList=jt});var $r=b(Hi=>{var _t=zr(),W=je(),$t=jr().ArraySet,nf=Vi().MappingList;function re(n){n||(n={}),this._file=W.getArg(n,"file",null),this._sourceRoot=W.getArg(n,"sourceRoot",null),this._skipValidation=W.getArg(n,"skipValidation",!1),this._ignoreInvalidMapping=W.getArg(n,"ignoreInvalidMapping",!1),this._sources=new $t,this._names=new $t,this._mappings=new nf,this._sourcesContents=null}re.prototype._version=3;re.fromSourceMap=function(e,t){var r=e.sourceRoot,i=new re(Object.assign(t||{},{file:e.file,sourceRoot:r}));return e.eachMapping(function(s){var o={generated:{line:s.generatedLine,column:s.generatedColumn}};s.source!=null&&(o.source=s.source,r!=null&&(o.source=W.relative(r,o.source)),o.original={line:s.originalLine,column:s.originalColumn},s.name!=null&&(o.name=s.name)),i.addMapping(o)}),e.sources.forEach(function(s){var o=s;r!==null&&(o=W.relative(r,s)),i._sources.has(o)||i._sources.add(o);var a=e.sourceContentFor(s);a!=null&&i.setSourceContent(s,a)}),i};re.prototype.addMapping=function(e){var t=W.getArg(e,"generated"),r=W.getArg(e,"original",null),i=W.getArg(e,"source",null),s=W.getArg(e,"name",null);!this._skipValidation&&this._validateMapping(t,r,i,s)===!1||(i!=null&&(i=String(i),this._sources.has(i)||this._sources.add(i)),s!=null&&(s=String(s),this._names.has(s)||this._names.add(s)),this._mappings.add({generatedLine:t.line,generatedColumn:t.column,originalLine:r!=null&&r.line,originalColumn:r!=null&&r.column,source:i,name:s}))};re.prototype.setSourceContent=function(e,t){var r=e;this._sourceRoot!=null&&(r=W.relative(this._sourceRoot,r)),t!=null?(this._sourcesContents||(this._sourcesContents=Object.create(null)),this._sourcesContents[W.toSetString(r)]=t):this._sourcesContents&&(delete this._sourcesContents[W.toSetString(r)],Object.keys(this._sourcesContents).length===0&&(this._sourcesContents=null))};re.prototype.applySourceMap=function(e,t,r){var i=t;if(t==null){if(e.file==null)throw new Error(`SourceMapGenerator.prototype.applySourceMap requires either an explicit source file, or the source map's "file" property. Both were omitted.`);i=e.file}var s=this._sourceRoot;s!=null&&(i=W.relative(s,i));var o=new $t,a=new $t;this._mappings.unsortedForEach(function(l){if(l.source===i&&l.originalLine!=null){var f=e.originalPositionFor({line:l.originalLine,column:l.originalColumn});f.source!=null&&(l.source=f.source,r!=null&&(l.source=W.join(r,l.source)),s!=null&&(l.source=W.relative(s,l.source)),l.originalLine=f.line,l.originalColumn=f.column,f.name!=null&&(l.name=f.name))}var u=l.source;u!=null&&!o.has(u)&&o.add(u);var h=l.name;h!=null&&!a.has(h)&&a.add(h)},this),this._sources=o,this._names=a,e.sources.forEach(function(l){var f=e.sourceContentFor(l);f!=null&&(r!=null&&(l=W.join(r,l)),s!=null&&(l=W.relative(s,l)),this.setSourceContent(l,f))},this)};re.prototype._validateMapping=function(e,t,r,i){if(t&&typeof t.line!="number"&&typeof t.column!="number"){var s="original.line and original.column are not numbers -- you probably meant to omit the original mapping entirely and only map the generated position. If so, pass null for the original mapping instead of an object with empty or null values.";if(this._ignoreInvalidMapping)return typeof console<"u"&&console.warn&&console.warn(s),!1;throw new Error(s)}if(!(e&&"line"in e&&"column"in e&&e.line>0&&e.column>=0&&!t&&!r&&!i)){if(e&&"line"in e&&"column"in e&&t&&"line"in t&&"column"in t&&e.line>0&&e.column>=0&&t.line>0&&t.column>=0&&r)return;var s="Invalid mapping: "+JSON.stringify({generated:e,source:r,original:t,name:i});if(this._ignoreInvalidMapping)return typeof console<"u"&&console.warn&&console.warn(s),!1;throw new Error(s)}};re.prototype._serializeMappings=function(){for(var e=0,t=1,r=0,i=0,s=0,o=0,a="",l,f,u,h,c=this._mappings.toArray(),d=0,m=c.length;d0){if(!W.compareByGeneratedPositionsInflated(f,c[d-1]))continue;l+=","}l+=_t.encode(f.generatedColumn-e),e=f.generatedColumn,f.source!=null&&(h=this._sources.indexOf(f.source),l+=_t.encode(h-o),o=h,l+=_t.encode(f.originalLine-1-i),i=f.originalLine-1,l+=_t.encode(f.originalColumn-r),r=f.originalColumn,f.name!=null&&(u=this._names.indexOf(f.name),l+=_t.encode(u-s),s=u)),a+=l}return a};re.prototype._generateSourcesContent=function(e,t){return e.map(function(r){if(!this._sourcesContents)return null;t!=null&&(r=W.relative(t,r));var i=W.toSetString(r);return Object.prototype.hasOwnProperty.call(this._sourcesContents,i)?this._sourcesContents[i]:null},this)};re.prototype.toJSON=function(){var e={version:this._version,sources:this._sources.toArray(),names:this._names.toArray(),mappings:this._serializeMappings()};return this._file!=null&&(e.file=this._file),this._sourceRoot!=null&&(e.sourceRoot=this._sourceRoot),this._sourcesContents&&(e.sourcesContent=this._generateSourcesContent(e.sources,e.sourceRoot)),e};re.prototype.toString=function(){return JSON.stringify(this.toJSON())};Hi.SourceMapGenerator=re});var Zi=b(Fe=>{Fe.GREATEST_LOWER_BOUND=1;Fe.LEAST_UPPER_BOUND=2;function Vr(n,e,t,r,i,s){var o=Math.floor((e-n)/2)+n,a=i(t,r[o],!0);return a===0?o:a>0?e-o>1?Vr(o,e,t,r,i,s):s==Fe.LEAST_UPPER_BOUND?e1?Vr(n,o,t,r,i,s):s==Fe.LEAST_UPPER_BOUND?o:n<0?-1:n}Fe.search=function(e,t,r,i){if(t.length===0)return-1;var s=Vr(-1,t.length,e,t,r,i||Fe.GREATEST_LOWER_BOUND);if(s<0)return-1;for(;s-1>=0&&r(t[s],t[s-1],!0)===0;)--s;return s}});var Ki=b(Xi=>{function sf(n){function e(i,s,o){var a=i[s];i[s]=i[o],i[o]=a}function t(i,s){return Math.round(i+Math.random()*(s-i))}function r(i,s,o,a){if(o{var S=je(),Zr=Zi(),$e=jr().ArraySet,lf=zr(),Et=Ki().quickSort;function M(n,e){var t=n;return typeof n=="string"&&(t=S.parseSourceMapInput(n)),t.sections!=null?new he(t,e):new H(t,e)}M.fromSourceMap=function(n,e){return H.fromSourceMap(n,e)};M.prototype._version=3;M.prototype.__generatedMappings=null;Object.defineProperty(M.prototype,"_generatedMappings",{configurable:!0,enumerable:!0,get:function(){return this.__generatedMappings||this._parseMappings(this._mappings,this.sourceRoot),this.__generatedMappings}});M.prototype.__originalMappings=null;Object.defineProperty(M.prototype,"_originalMappings",{configurable:!0,enumerable:!0,get:function(){return this.__originalMappings||this._parseMappings(this._mappings,this.sourceRoot),this.__originalMappings}});M.prototype._charIsMappingSeparator=function(e,t){var r=e.charAt(t);return r===";"||r===","};M.prototype._parseMappings=function(e,t){throw new Error("Subclasses must implement _parseMappings")};M.GENERATED_ORDER=1;M.ORIGINAL_ORDER=2;M.GREATEST_LOWER_BOUND=1;M.LEAST_UPPER_BOUND=2;M.prototype.eachMapping=function(e,t,r){var i=t||null,s=r||M.GENERATED_ORDER,o;switch(s){case M.GENERATED_ORDER:o=this._generatedMappings;break;case M.ORIGINAL_ORDER:o=this._originalMappings;break;default:throw new Error("Unknown order of iteration.")}for(var a=this.sourceRoot,l=e.bind(i),f=this._names,u=this._sources,h=this._sourceMapURL,c=0,d=o.length;c=0){var o=this._originalMappings[s];if(e.column===void 0)for(var a=o.originalLine;o&&o.originalLine===a;)i.push({line:S.getArg(o,"generatedLine",null),column:S.getArg(o,"generatedColumn",null),lastColumn:S.getArg(o,"lastGeneratedColumn",null)}),o=this._originalMappings[++s];else for(var l=o.originalColumn;o&&o.originalLine===t&&o.originalColumn==l;)i.push({line:S.getArg(o,"generatedLine",null),column:S.getArg(o,"generatedColumn",null),lastColumn:S.getArg(o,"lastGeneratedColumn",null)}),o=this._originalMappings[++s]}return i};Vt.SourceMapConsumer=M;function H(n,e){var t=n;typeof n=="string"&&(t=S.parseSourceMapInput(n));var r=S.getArg(t,"version"),i=S.getArg(t,"sources"),s=S.getArg(t,"names",[]),o=S.getArg(t,"sourceRoot",null),a=S.getArg(t,"sourcesContent",null),l=S.getArg(t,"mappings"),f=S.getArg(t,"file",null);if(r!=this._version)throw new Error("Unsupported version: "+r);o&&(o=S.normalize(o)),i=i.map(String).map(S.normalize).map(function(u){return o&&S.isAbsolute(o)&&S.isAbsolute(u)?S.relative(o,u):u}),this._names=$e.fromArray(s.map(String),!0),this._sources=$e.fromArray(i,!0),this._absoluteSources=this._sources.toArray().map(function(u){return S.computeSourceURL(o,u,e)}),this.sourceRoot=o,this.sourcesContent=a,this._mappings=l,this._sourceMapURL=e,this.file=f}H.prototype=Object.create(M.prototype);H.prototype.consumer=M;H.prototype._findSourceIndex=function(n){var e=n;if(this.sourceRoot!=null&&(e=S.relative(this.sourceRoot,e)),this._sources.has(e))return this._sources.indexOf(e);var t;for(t=0;t0&&(n[e]=s,n[e+1]=i)}else if(r<20)for(let i=e;ie;s--){let o=n[s-1],a=n[s];if(Hr(o,a)<=0)break;n[s-1]=a,n[s]=o}else Et(n,Hr,e)}H.prototype._parseMappings=function(e,t){var r=1,i=0,s=0,o=0,a=0,l=0,f=e.length,u=0,h={},c={},d=[],m=[],p,_,v,C,I;let L=0;for(;u1&&(p.source=a+v[1],a+=v[1],p.originalLine=s+v[2],s=p.originalLine,p.originalLine+=1,p.originalColumn=o+v[3],o=p.originalColumn,v.length>4&&(p.name=l+v[4],l+=v[4])),m.push(p),typeof p.originalLine=="number"){let O=p.source;for(;d.length<=O;)d.push(null);d[O]===null&&(d[O]=[]),d[O].push(p)}}Ji(m,L),this.__generatedMappings=m;for(var R=0;R=0){var i=this._generatedMappings[r];if(i.generatedLine===t.generatedLine){var s=S.getArg(i,"source",null);s!==null&&(s=this._sources.at(s),s=S.computeSourceURL(this.sourceRoot,s,this._sourceMapURL));var o=S.getArg(i,"name",null);return o!==null&&(o=this._names.at(o)),{source:s,line:S.getArg(i,"originalLine",null),column:S.getArg(i,"originalColumn",null),name:o}}}return{source:null,line:null,column:null,name:null}};H.prototype.hasContentsOfAllSources=function(){return this.sourcesContent?this.sourcesContent.length>=this._sources.size()&&!this.sourcesContent.some(function(e){return e==null}):!1};H.prototype.sourceContentFor=function(e,t){if(!this.sourcesContent)return null;var r=this._findSourceIndex(e);if(r>=0)return this.sourcesContent[r];var i=e;this.sourceRoot!=null&&(i=S.relative(this.sourceRoot,i));var s;if(this.sourceRoot!=null&&(s=S.urlParse(this.sourceRoot))){var o=i.replace(/^file:\/\//,"");if(s.scheme=="file"&&this._sources.has(o))return this.sourcesContent[this._sources.indexOf(o)];if((!s.path||s.path=="/")&&this._sources.has("/"+i))return this.sourcesContent[this._sources.indexOf("/"+i)]}if(t)return null;throw new Error('"'+i+'" is not in the SourceMap.')};H.prototype.generatedPositionFor=function(e){var t=S.getArg(e,"source");if(t=this._findSourceIndex(t),t<0)return{line:null,column:null,lastColumn:null};var r={source:t,originalLine:S.getArg(e,"line"),originalColumn:S.getArg(e,"column")},i=this._findMapping(r,this._originalMappings,"originalLine","originalColumn",S.compareByOriginalPositions,S.getArg(e,"bias",M.GREATEST_LOWER_BOUND));if(i>=0){var s=this._originalMappings[i];if(s.source===r.source)return{line:S.getArg(s,"generatedLine",null),column:S.getArg(s,"generatedColumn",null),lastColumn:S.getArg(s,"lastGeneratedColumn",null)}}return{line:null,column:null,lastColumn:null}};Vt.BasicSourceMapConsumer=H;function he(n,e){var t=n;typeof n=="string"&&(t=S.parseSourceMapInput(n));var r=S.getArg(t,"version"),i=S.getArg(t,"sections");if(r!=this._version)throw new Error("Unsupported version: "+r);this._sources=new $e,this._names=new $e;var s={line:-1,column:0};this._sections=i.map(function(o){if(o.url)throw new Error("Support for url field in sections not implemented.");var a=S.getArg(o,"offset"),l=S.getArg(a,"line"),f=S.getArg(a,"column");if(l{var af=$r().SourceMapGenerator,Ht=je(),ff=/(\r?\n)/,uf=10,Ve="$$$isSourceNode$$$";function Q(n,e,t,r,i){this.children=[],this.sourceContents={},this.line=n??null,this.column=e??null,this.source=t??null,this.name=i??null,this[Ve]=!0,r!=null&&this.add(r)}Q.fromStringWithSourceMap=function(e,t,r){var i=new Q,s=e.split(ff),o=0,a=function(){var c=m(),d=m()||"";return c+d;function m(){return o=0;t--)this.prepend(e[t]);else if(e[Ve]||typeof e=="string")this.children.unshift(e);else throw new TypeError("Expected a SourceNode, string, or an array of SourceNodes and strings. Got "+e);return this};Q.prototype.walk=function(e){for(var t,r=0,i=this.children.length;r0){for(t=[],r=0;r{Zt.SourceMapGenerator=$r().SourceMapGenerator;Zt.SourceMapConsumer=es().SourceMapConsumer;Zt.SourceNode=rs().SourceNode});var os=b((qh,ss)=>{"use strict";var{existsSync:cf,readFileSync:hf}=require("fs"),{dirname:Xr,join:df}=require("path"),{SourceMapConsumer:ns,SourceMapGenerator:is}=Yr();function pf(n){return Buffer?Buffer.from(n,"base64").toString():window.atob(n)}var wt=class{constructor(e,t){if(t.map===!1)return;this.loadAnnotation(e),this.inline=this.startWith(this.annotation,"data:");let r=t.map?t.map.prev:void 0,i=this.loadMap(t.from,r);!this.mapFile&&t.from&&(this.mapFile=t.from),this.mapFile&&(this.root=Xr(this.mapFile)),i&&(this.text=i)}consumer(){return this.consumerCache||(this.consumerCache=new ns(this.text)),this.consumerCache}decodeInline(e){let t=/^data:application\/json;charset=utf-?8;base64,/,r=/^data:application\/json;base64,/,i=/^data:application\/json;charset=utf-?8,/,s=/^data:application\/json,/,o=e.match(i)||e.match(s);if(o)return decodeURIComponent(e.substr(o[0].length));let a=e.match(t)||e.match(r);if(a)return pf(e.substr(a[0].length));let l=e.match(/data:application\/json;([^,]+),/)[1];throw new Error("Unsupported source map encoding "+l)}getAnnotationURL(e){return e.replace(/^\/\*\s*# sourceMappingURL=/,"").trim()}isMap(e){return typeof e!="object"?!1:typeof e.mappings=="string"||typeof e._mappings=="string"||Array.isArray(e.sections)}loadAnnotation(e){let t=e.match(/\/\*\s*# sourceMappingURL=/g);if(!t)return;let r=e.lastIndexOf(t.pop()),i=e.indexOf("*/",r);r>-1&&i>-1&&(this.annotation=this.getAnnotationURL(e.substring(r,i)))}loadFile(e){if(this.root=Xr(e),cf(e))return this.mapFile=e,hf(e,"utf-8").toString().trim()}loadMap(e,t){if(t===!1)return!1;if(t){if(typeof t=="string")return t;if(typeof t=="function"){let r=t(e);if(r){let i=this.loadFile(r);if(!i)throw new Error("Unable to load previous source map: "+r.toString());return i}}else{if(t instanceof ns)return is.fromSourceMap(t).toString();if(t instanceof is)return t.toString();if(this.isMap(t))return JSON.stringify(t);throw new Error("Unsupported previous source map format: "+t.toString())}}else{if(this.inline)return this.decodeInline(this.annotation);if(this.annotation){let r=this.annotation;return e&&(r=df(Xr(e),r)),this.loadFile(r)}}}startWith(e,t){return e?e.substr(0,t.length)===t:!1}withContent(){return!!(this.consumer().sourcesContent&&this.consumer().sourcesContent.length>0)}};ss.exports=wt;wt.default=wt});var hs=b((jh,cs)=>{"use strict";var{nanoid:mf}=Ri(),{isAbsolute:Qr,resolve:en}=require("path"),{SourceMapConsumer:gf,SourceMapGenerator:_f}=Yr(),{fileURLToPath:ls,pathToFileURL:Yt}=require("url"),as=Or(),Ef=os(),Kr=Lr(),Jr=Symbol("lineToIndexCache"),wf=!!(gf&&_f),fs=!!(en&&Qr);function us(n){if(n[Jr])return n[Jr];let e=n.css.split(` +`),t=new Array(e.length),r=0;for(let i=0,s=e.length;i"u"||typeof e=="object"&&!e.toString)throw new Error(`PostCSS received ${e} instead of CSS string`);if(this.css=e.toString(),this.css[0]==="\uFEFF"||this.css[0]==="\uFFFE"?(this.hasBOM=!0,this.css=this.css.slice(1)):this.hasBOM=!1,this.document=this.css,t.document&&(this.document=t.document.toString()),t.from&&(!fs||/^\w+:\/\//.test(t.from)||Qr(t.from)?this.file=t.from:this.file=en(t.from)),fs&&wf){let r=new Ef(this.css,t);if(r.text){this.map=r;let i=r.consumer().file;!this.file&&i&&(this.file=this.mapResolve(i))}}this.file||(this.id=""),this.map&&(this.map.file=this.from)}error(e,t,r,i={}){let s,o,a,l,f;if(t&&typeof t=="object"){let h=t,c=r;if(typeof h.offset=="number"){l=h.offset;let d=this.fromOffset(l);t=d.line,r=d.col}else t=h.line,r=h.column,l=this.fromLineAndColumn(t,r);if(typeof c.offset=="number"){a=c.offset;let d=this.fromOffset(a);o=d.line,s=d.col}else o=c.line,s=c.column,a=this.fromLineAndColumn(c.line,c.column)}else if(r)l=this.fromLineAndColumn(t,r);else{l=t;let h=this.fromOffset(l);t=h.line,r=h.col}let u=this.origin(t,r,o,s);return u?f=new as(e,u.endLine===void 0?u.line:{column:u.column,line:u.line},u.endLine===void 0?u.column:{column:u.endColumn,line:u.endLine},u.source,u.file,i.plugin):f=new as(e,o===void 0?t:{column:r,line:t},o===void 0?r:{column:s,line:o},this.css,this.file,i.plugin),f.input={column:r,endColumn:s,endLine:o,endOffset:a,line:t,offset:l,source:this.css},this.file&&(Yt&&(f.input.url=Yt(this.file).toString()),f.input.file=this.file),f}fromLineAndColumn(e,t){return us(this)[e-1]+t-1}fromOffset(e){let t=us(this),r=t[t.length-1],i=0;if(e>=r)i=t.length-1;else{let s=t.length-2,o;for(;i>1),e=t[o+1])i=o+1;else{i=o;break}}return{col:e-t[i]+1,line:i+1}}mapResolve(e){return/^\w+:\/\//.test(e)?e:en(this.map.consumer().sourceRoot||this.map.root||".",e)}origin(e,t,r,i){if(!this.map)return!1;let s=this.map.consumer(),o=s.originalPositionFor({column:t,line:e});if(!o.source)return!1;let a;typeof r=="number"&&(a=s.originalPositionFor({column:i,line:r}));let l;Qr(o.source)?l=Yt(o.source):l=new URL(o.source,this.map.consumer().sourceRoot||Yt(this.map.mapFile));let f={column:o.column,endColumn:a&&a.column,endLine:a&&a.line,line:o.line,url:l.toString()};if(l.protocol==="file:")if(ls)f.file=ls(l);else throw new Error("file: protocol is not available in this PostCSS build");let u=s.sourceContentFor(o.source);return u&&(f.source=u),f}toJSON(){let e={};for(let t of["hasBOM","css","file","id"])this[t]!=null&&(e[t]=this[t]);return this.map&&(e.map={...this.map},e.map.consumerCache&&(e.map.consumerCache=void 0)),e}};cs.exports=He;He.default=He;Kr&&Kr.registerInput&&Kr.registerInput(He)});var ms=b(($h,ps)=>{"use strict";var ds=mt(),Ze=class extends ds{constructor(e){super(e),this.type="atrule"}append(...e){return this.proxyOf.nodes||(this.nodes=[]),super.append(...e)}prepend(...e){return this.proxyOf.nodes||(this.nodes=[]),super.prepend(...e)}};ps.exports=Ze;Ze.default=Ze;ds.registerAtRule(Ze)});var ys=b((Vh,ws)=>{"use strict";var gs=mt(),_s,Es,Ce=class extends gs{constructor(e){super(e),this.type="root",this.nodes||(this.nodes=[])}normalize(e,t,r){let i=super.normalize(e);if(t){if(r==="prepend")this.nodes.length>1?t.raws.before=this.nodes[1].raws.before:delete t.raws.before;else if(this.first!==t)for(let s of i)s.raws.before=t.raws.before}return i}removeChild(e,t){let r=this.index(e);return!t&&r===0&&this.nodes.length>1&&(this.nodes[1].raws.before=this.nodes[r].raws.before),super.removeChild(e)}toResult(e={}){return new _s(new Es,this,e).stringify()}};Ce.registerLazyResult=n=>{_s=n};Ce.registerProcessor=n=>{Es=n};ws.exports=Ce;Ce.default=Ce;gs.registerRoot(Ce)});var vs=b((Hh,Ss)=>{"use strict";var yt={comma(n){return yt.split(n,[","],!0)},space(n){let e=[" ",` +`," "];return yt.split(n,e)},split(n,e,t){let r=[],i="",s=!1,o=0,a=!1,l="",f=!1;for(let u of n)f?f=!1:u==="\\"?f=!0:a?u===l&&(a=!1):u==='"'||u==="'"?(a=!0,l=u):u==="("?o+=1:u===")"?o>0&&(o-=1):o===0&&e.includes(u)&&(s=!0),s?(i!==""&&r.push(i.trim()),i="",s=!1):i+=u;return(t||i!=="")&&r.push(i.trim()),r}};Ss.exports=yt;yt.default=yt});var bs=b((Zh,Cs)=>{"use strict";var xs=mt(),yf=vs(),Ye=class extends xs{get selectors(){return yf.comma(this.selector)}set selectors(e){let t=this.selector?this.selector.match(/,\s*/):null,r=t?t[0]:","+this.raw("between","beforeOpen");this.selector=e.join(r)}constructor(e){super(e),this.type="rule",this.nodes||(this.nodes=[])}};Cs.exports=Ye;Ye.default=Ye;xs.registerRule(Ye)});var Ns=b((Yh,Is)=>{"use strict";var Sf=ms(),vf=Dr(),xf=Mr(),Cf=ys(),Ls=bs(),bf=br(),Os={empty:!0,space:!0};function Lf(n){for(let e=n.length-1;e>=0;e--){let t=n[e],r=t[3]||t[2];if(r)return r}}var tn=class{constructor(e){this.input=e,this.root=new Cf,this.current=this.root,this.spaces="",this.semicolon=!1,this.createTokenizer(),this.root.source={input:e,start:{column:1,line:1,offset:0}}}atrule(e){let t=new Sf;t.name=e[1].slice(1),t.name===""&&this.unnamedAtrule(t,e),this.init(t,e[2]);let r,i,s,o=!1,a=!1,l=[],f=[];for(;!this.tokenizer.endOfFile();){if(e=this.tokenizer.nextToken(),r=e[0],r==="("||r==="["?f.push(r==="("?")":"]"):r==="{"&&f.length>0?f.push("}"):r===f[f.length-1]&&f.pop(),f.length===0)if(r===";"){t.source.end=this.getPosition(e[2]),t.source.end.offset++,this.semicolon=!0;break}else if(r==="{"){a=!0;break}else if(r==="}"){if(l.length>0){for(s=l.length-1,i=l[s];i&&i[0]==="space";)i=l[--s];i&&(t.source.end=this.getPosition(i[3]||i[2]),t.source.end.offset++)}this.end(e);break}else l.push(e);else l.push(e);if(this.tokenizer.endOfFile()){o=!0;break}}t.raws.between=this.spacesAndCommentsFromEnd(l),l.length?(t.raws.afterName=this.spacesAndCommentsFromStart(l),this.raw(t,"params",l),o&&(e=l[l.length-1],t.source.end=this.getPosition(e[3]||e[2]),t.source.end.offset++,this.spaces=t.raws.between,t.raws.between="")):(t.raws.afterName="",t.params=""),a&&(t.nodes=[],this.current=t)}checkMissedSemicolon(e){let t=this.colon(e);if(t===!1)return;let r=0,i;for(let s=t-1;s>=0&&(i=e[s],!(i[0]!=="space"&&(r+=1,r===2)));s--);throw this.input.error("Missed semicolon",i[0]==="word"?i[3]+1:i[2])}colon(e){let t=0,r,i,s;for(let[o,a]of e.entries()){if(i=a,s=i[0],s==="("&&(t+=1),s===")"&&(t-=1),t===0&&s===":")if(!r)this.doubleColon(i);else{if(r[0]==="word"&&r[1]==="progid")continue;return o}r=i}return!1}comment(e){let t=new vf;this.init(t,e[2]),t.source.end=this.getPosition(e[3]||e[2]),t.source.end.offset++;let r=e[1].slice(2,-2);if(/^\s*$/.test(r))t.text="",t.raws.left=r,t.raws.right="";else{let i=r.match(/^(\s*)([^]*\S)(\s*)$/);t.text=i[2],t.raws.left=i[1],t.raws.right=i[3]}}createTokenizer(){this.tokenizer=bf(this.input)}decl(e,t){let r=new xf;this.init(r,e[0][2]);let i=e[e.length-1];for(i[0]===";"&&(this.semicolon=!0,e.pop()),r.source.end=this.getPosition(i[3]||i[2]||Lf(e)),r.source.end.offset++;e[0][0]!=="word";)e.length===1&&this.unknownWord(e),r.raws.before+=e.shift()[1];for(r.source.start=this.getPosition(e[0][2]),r.prop="";e.length;){let f=e[0][0];if(f===":"||f==="space"||f==="comment")break;r.prop+=e.shift()[1]}r.raws.between="";let s;for(;e.length;)if(s=e.shift(),s[0]===":"){r.raws.between+=s[1];break}else s[0]==="word"&&/\w/.test(s[1])&&this.unknownWord([s]),r.raws.between+=s[1];(r.prop[0]==="_"||r.prop[0]==="*")&&(r.raws.before+=r.prop[0],r.prop=r.prop.slice(1));let o=[],a;for(;e.length&&(a=e[0][0],!(a!=="space"&&a!=="comment"));)o.push(e.shift());this.precheckMissedSemicolon(e);for(let f=e.length-1;f>=0;f--){if(s=e[f],s[1].toLowerCase()==="!important"){r.important=!0;let u=this.stringFrom(e,f);u=this.spacesFromEnd(e)+u,u!==" !important"&&(r.raws.important=u);break}else if(s[1].toLowerCase()==="important"){let u=e.slice(0),h="";for(let c=f;c>0;c--){let d=u[c][0];if(h.trim().startsWith("!")&&d!=="space")break;h=u.pop()[1]+h}h.trim().startsWith("!")&&(r.important=!0,r.raws.important=h,e=u)}if(s[0]!=="space"&&s[0]!=="comment")break}e.some(f=>f[0]!=="space"&&f[0]!=="comment")&&(r.raws.between+=o.map(f=>f[1]).join(""),o=[]),this.raw(r,"value",o.concat(e),t),r.value.includes(":")&&!t&&this.checkMissedSemicolon(e)}doubleColon(e){throw this.input.error("Double colon",{offset:e[2]},{offset:e[2]+e[1].length})}emptyRule(e){let t=new Ls;this.init(t,e[2]),t.selector="",t.raws.between="",this.current=t}end(e){this.current.nodes&&this.current.nodes.length&&(this.current.raws.semicolon=this.semicolon),this.semicolon=!1,this.current.raws.after=(this.current.raws.after||"")+this.spaces,this.spaces="",this.current.parent?(this.current.source.end=this.getPosition(e[2]),this.current.source.end.offset++,this.current=this.current.parent):this.unexpectedClose(e)}endFile(){this.current.parent&&this.unclosedBlock(),this.current.nodes&&this.current.nodes.length&&(this.current.raws.semicolon=this.semicolon),this.current.raws.after=(this.current.raws.after||"")+this.spaces,this.root.source.end=this.getPosition(this.tokenizer.position())}freeSemicolon(e){if(this.spaces+=e[1],this.current.nodes){let t=this.current.nodes[this.current.nodes.length-1];t&&t.type==="rule"&&!t.raws.ownSemicolon&&(t.raws.ownSemicolon=this.spaces,this.spaces="",t.source.end=this.getPosition(e[2]),t.source.end.offset+=t.raws.ownSemicolon.length)}}getPosition(e){let t=this.input.fromOffset(e);return{column:t.col,line:t.line,offset:e}}init(e,t){this.current.push(e),e.source={input:this.input,start:this.getPosition(t)},e.raws.before=this.spaces,this.spaces="",e.type!=="comment"&&(this.semicolon=!1)}other(e){let t=!1,r=null,i=!1,s=null,o=[],a=e[1].startsWith("--"),l=[],f=e;for(;f;){if(r=f[0],l.push(f),r==="("||r==="[")s||(s=f),o.push(r==="("?")":"]");else if(a&&i&&r==="{")s||(s=f),o.push("}");else if(o.length===0)if(r===";")if(i){this.decl(l,a);return}else break;else if(r==="{"){this.rule(l);return}else if(r==="}"){this.tokenizer.back(l.pop()),t=!0;break}else r===":"&&(i=!0);else r===o[o.length-1]&&(o.pop(),o.length===0&&(s=null));f=this.tokenizer.nextToken()}if(this.tokenizer.endOfFile()&&(t=!0),o.length>0&&this.unclosedBracket(s),t&&i){if(!a)for(;l.length&&(f=l[l.length-1][0],!(f!=="space"&&f!=="comment"));)this.tokenizer.back(l.pop());this.decl(l,a)}else this.unknownWord(l)}parse(){let e;for(;!this.tokenizer.endOfFile();)switch(e=this.tokenizer.nextToken(),e[0]){case"space":this.spaces+=e[1];break;case";":this.freeSemicolon(e);break;case"}":this.end(e);break;case"comment":this.comment(e);break;case"at-word":this.atrule(e);break;case"{":this.emptyRule(e);break;default:this.other(e);break}this.endFile()}precheckMissedSemicolon(){}raw(e,t,r,i){let s,o,a=r.length,l="",f=!0,u,h;for(let c=0;cd+m[1],"");e.raws[t]={raw:c,value:l}}e[t]=l}rule(e){e.pop();let t=new Ls;this.init(t,e[0][2]),t.raws.between=this.spacesAndCommentsFromEnd(e),this.raw(t,"selector",e),this.current=t}spacesAndCommentsFromEnd(e){let t,r="";for(;e.length&&(t=e[e.length-1][0],!(t!=="space"&&t!=="comment"));)r=e.pop()[1]+r;return r}spacesAndCommentsFromStart(e){let t,r="";for(;e.length&&(t=e[0][0],!(t!=="space"&&t!=="comment"));)r+=e.shift()[1];return r}spacesFromEnd(e){let t,r="";for(;e.length&&(t=e[e.length-1][0],t==="space");)r=e.pop()[1]+r;return r}stringFrom(e,t){let r="";for(let i=t;i{"use strict";var Of=mt(),If=hs(),Nf=Ns();function Xt(n,e){let t=new If(n,e),r=new Nf(t);try{r.parse()}catch(i){throw process.env.NODE_ENV!=="production"&&i.name==="CssSyntaxError"&&e&&e.from&&(/\.scss$/i.test(e.from)?i.message+=` +You tried to parse SCSS with the standard CSS parser; try again with the postcss-scss parser`:/\.sass/i.test(e.from)?i.message+=` +You tried to parse Sass with the standard CSS parser; try again with the postcss-sass parser`:/\.less$/i.test(e.from)&&(i.message+=` +You tried to parse Less with the standard CSS parser; try again with the postcss-less parser`)),i}return r.root}Ts.exports=Xt;Xt.default=Xt;Of.registerParse(Xt)});var we=b((Kh,Ms)=>{"use strict";var As=["nodebuffer","arraybuffer","fragments"],Ds=typeof Blob<"u";Ds&&As.push("blob");Ms.exports={BINARY_TYPES:As,EMPTY_BUFFER:Buffer.alloc(0),GUID:"258EAFA5-E914-47DA-95CA-C5AB0DC85B11",hasBlob:Ds,kForOnEventAttribute:Symbol("kIsForOnEventAttribute"),kListener:Symbol("kListener"),kStatusCode:Symbol("status-code"),kWebSocket:Symbol("websocket"),NOOP:()=>{}}});var St=b((Jh,Kt)=>{"use strict";var{EMPTY_BUFFER:Tf}=we(),rn=Buffer[Symbol.species];function Rf(n,e){if(n.length===0)return Tf;if(n.length===1)return n[0];let t=Buffer.allocUnsafe(e),r=0;for(let i=0;i{"use strict";var Us=Symbol("kDone"),sn=Symbol("kRun"),on=class{constructor(e){this[Us]=()=>{this.pending--,this[sn]()},this.concurrency=e||1/0,this.jobs=[],this.pending=0}add(e){this.jobs.push(e),this[sn]()}[sn](){if(this.pending!==this.concurrency&&this.jobs.length){let e=this.jobs.shift();this.pending++,e(this[Us])}}};ks.exports=on});var xt=b((ed,qs)=>{"use strict";var vt=require("zlib"),zs=St(),Df=Bs(),{kStatusCode:Gs}=we(),Mf=Buffer[Symbol.species],Pf=Buffer.from([0,0,255,255]),Qt=Symbol("permessage-deflate"),ye=Symbol("total-length"),Xe=Symbol("callback"),be=Symbol("buffers"),Ke=Symbol("error"),Jt,ln=class{constructor(e,t,r){if(this._maxPayload=r|0,this._options=e||{},this._threshold=this._options.threshold!==void 0?this._options.threshold:1024,this._isServer=!!t,this._deflate=null,this._inflate=null,this.params=null,!Jt){let i=this._options.concurrencyLimit!==void 0?this._options.concurrencyLimit:10;Jt=new Df(i)}}static get extensionName(){return"permessage-deflate"}offer(){let e={};return this._options.serverNoContextTakeover&&(e.server_no_context_takeover=!0),this._options.clientNoContextTakeover&&(e.client_no_context_takeover=!0),this._options.serverMaxWindowBits&&(e.server_max_window_bits=this._options.serverMaxWindowBits),this._options.clientMaxWindowBits?e.client_max_window_bits=this._options.clientMaxWindowBits:this._options.clientMaxWindowBits==null&&(e.client_max_window_bits=!0),e}accept(e){return e=this.normalizeParams(e),this.params=this._isServer?this.acceptAsServer(e):this.acceptAsClient(e),this.params}cleanup(){if(this._inflate&&(this._inflate.close(),this._inflate=null),this._deflate){let e=this._deflate[Xe];this._deflate.close(),this._deflate=null,e&&e(new Error("The deflate stream was closed while data was being processed"))}}acceptAsServer(e){let t=this._options,r=e.find(i=>!(t.serverNoContextTakeover===!1&&i.server_no_context_takeover||i.server_max_window_bits&&(t.serverMaxWindowBits===!1||typeof t.serverMaxWindowBits=="number"&&t.serverMaxWindowBits>i.server_max_window_bits)||typeof t.clientMaxWindowBits=="number"&&!i.client_max_window_bits));if(!r)throw new Error("None of the extension offers can be accepted");return t.serverNoContextTakeover&&(r.server_no_context_takeover=!0),t.clientNoContextTakeover&&(r.client_no_context_takeover=!0),typeof t.serverMaxWindowBits=="number"&&(r.server_max_window_bits=t.serverMaxWindowBits),typeof t.clientMaxWindowBits=="number"?r.client_max_window_bits=t.clientMaxWindowBits:(r.client_max_window_bits===!0||t.clientMaxWindowBits===!1)&&delete r.client_max_window_bits,r}acceptAsClient(e){let t=e[0];if(this._options.clientNoContextTakeover===!1&&t.client_no_context_takeover)throw new Error('Unexpected parameter "client_no_context_takeover"');if(!t.client_max_window_bits)typeof this._options.clientMaxWindowBits=="number"&&(t.client_max_window_bits=this._options.clientMaxWindowBits);else if(this._options.clientMaxWindowBits===!1||typeof this._options.clientMaxWindowBits=="number"&&t.client_max_window_bits>this._options.clientMaxWindowBits)throw new Error('Unexpected or invalid parameter "client_max_window_bits"');return t}normalizeParams(e){return e.forEach(t=>{Object.keys(t).forEach(r=>{let i=t[r];if(i.length>1)throw new Error(`Parameter "${r}" must have only a single value`);if(i=i[0],r==="client_max_window_bits"){if(i!==!0){let s=+i;if(!Number.isInteger(s)||s<8||s>15)throw new TypeError(`Invalid value for parameter "${r}": ${i}`);i=s}else if(!this._isServer)throw new TypeError(`Invalid value for parameter "${r}": ${i}`)}else if(r==="server_max_window_bits"){let s=+i;if(!Number.isInteger(s)||s<8||s>15)throw new TypeError(`Invalid value for parameter "${r}": ${i}`);i=s}else if(r==="client_no_context_takeover"||r==="server_no_context_takeover"){if(i!==!0)throw new TypeError(`Invalid value for parameter "${r}": ${i}`)}else throw new Error(`Unknown parameter "${r}"`);t[r]=i})}),e}decompress(e,t,r){Jt.add(i=>{this._decompress(e,t,(s,o)=>{i(),r(s,o)})})}compress(e,t,r){Jt.add(i=>{this._compress(e,t,(s,o)=>{i(),r(s,o)})})}_decompress(e,t,r){let i=this._isServer?"client":"server";if(!this._inflate){let s=`${i}_max_window_bits`,o=typeof this.params[s]!="number"?vt.Z_DEFAULT_WINDOWBITS:this.params[s];this._inflate=vt.createInflateRaw({...this._options.zlibInflateOptions,windowBits:o}),this._inflate[Qt]=this,this._inflate[ye]=0,this._inflate[be]=[],this._inflate.on("error",Uf),this._inflate.on("data",Ws)}this._inflate[Xe]=r,this._inflate.write(e),t&&this._inflate.write(Pf),this._inflate.flush(()=>{let s=this._inflate[Ke];if(s){this._inflate.close(),this._inflate=null,r(s);return}let o=zs.concat(this._inflate[be],this._inflate[ye]);this._inflate._readableState.endEmitted?(this._inflate.close(),this._inflate=null):(this._inflate[ye]=0,this._inflate[be]=[],t&&this.params[`${i}_no_context_takeover`]&&this._inflate.reset()),r(null,o)})}_compress(e,t,r){let i=this._isServer?"server":"client";if(!this._deflate){let s=`${i}_max_window_bits`,o=typeof this.params[s]!="number"?vt.Z_DEFAULT_WINDOWBITS:this.params[s];this._deflate=vt.createDeflateRaw({...this._options.zlibDeflateOptions,windowBits:o}),this._deflate[ye]=0,this._deflate[be]=[],this._deflate.on("data",Ff)}this._deflate[Xe]=r,this._deflate.write(e),this._deflate.flush(vt.Z_SYNC_FLUSH,()=>{if(!this._deflate)return;let s=zs.concat(this._deflate[be],this._deflate[ye]);t&&(s=new Mf(s.buffer,s.byteOffset,s.length-4)),this._deflate[Xe]=null,this._deflate[ye]=0,this._deflate[be]=[],t&&this.params[`${i}_no_context_takeover`]&&this._deflate.reset(),r(null,s)})}};qs.exports=ln;function Ff(n){this[be].push(n),this[ye]+=n.length}function Ws(n){if(this[ye]+=n.length,this[Qt]._maxPayload<1||this[ye]<=this[Qt]._maxPayload){this[be].push(n);return}this[Ke]=new RangeError("Max payload size exceeded"),this[Ke].code="WS_ERR_UNSUPPORTED_MESSAGE_LENGTH",this[Ke][Gs]=1009,this.removeListener("data",Ws),this.reset()}function Uf(n){if(this[Qt]._inflate=null,this[Ke]){this[Xe](this[Ke]);return}n[Gs]=1007,this[Xe](n)}});var Je=b((td,er)=>{"use strict";var{isUtf8:js}=require("buffer"),{hasBlob:kf}=we(),Bf=[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,1,1,1,1,0,0,1,1,0,1,1,0,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,0,1,0];function zf(n){return n>=1e3&&n<=1014&&n!==1004&&n!==1005&&n!==1006||n>=3e3&&n<=4999}function an(n){let e=n.length,t=0;for(;t=e||(n[t+1]&192)!==128||(n[t+2]&192)!==128||n[t]===224&&(n[t+1]&224)===128||n[t]===237&&(n[t+1]&224)===160)return!1;t+=3}else if((n[t]&248)===240){if(t+3>=e||(n[t+1]&192)!==128||(n[t+2]&192)!==128||(n[t+3]&192)!==128||n[t]===240&&(n[t+1]&240)===128||n[t]===244&&n[t+1]>143||n[t]>244)return!1;t+=4}else return!1;return!0}function Gf(n){return kf&&typeof n=="object"&&typeof n.arrayBuffer=="function"&&typeof n.type=="string"&&typeof n.stream=="function"&&(n[Symbol.toStringTag]==="Blob"||n[Symbol.toStringTag]==="File")}er.exports={isBlob:Gf,isValidStatusCode:zf,isValidUTF8:an,tokenChars:Bf};if(js)er.exports.isValidUTF8=function(n){return n.length<24?an(n):js(n)};else if(!process.env.WS_NO_UTF_8_VALIDATE)try{let n=require("utf-8-validate");er.exports.isValidUTF8=function(e){return e.length<32?an(e):n(e)}}catch{}});var dn=b((rd,Ks)=>{"use strict";var{Writable:Wf}=require("stream"),$s=xt(),{BINARY_TYPES:qf,EMPTY_BUFFER:Vs,kStatusCode:jf,kWebSocket:$f}=we(),{concat:fn,toArrayBuffer:Vf,unmask:Hf}=St(),{isValidStatusCode:Zf,isValidUTF8:Hs}=Je(),tr=Buffer[Symbol.species],ne=0,Zs=1,Ys=2,Xs=3,un=4,cn=5,rr=6,hn=class extends Wf{constructor(e={}){super(),this._allowSynchronousEvents=e.allowSynchronousEvents!==void 0?e.allowSynchronousEvents:!0,this._binaryType=e.binaryType||qf[0],this._extensions=e.extensions||{},this._isServer=!!e.isServer,this._maxPayload=e.maxPayload|0,this._skipUTF8Validation=!!e.skipUTF8Validation,this[$f]=void 0,this._bufferedBytes=0,this._buffers=[],this._compressed=!1,this._payloadLength=0,this._mask=void 0,this._fragmented=0,this._masked=!1,this._fin=!1,this._opcode=0,this._totalPayloadLength=0,this._messageLength=0,this._fragments=[],this._errored=!1,this._loop=!1,this._state=ne}_write(e,t,r){if(this._opcode===8&&this._state==ne)return r();this._bufferedBytes+=e.length,this._buffers.push(e),this.startLoop(r)}consume(e){if(this._bufferedBytes-=e,e===this._buffers[0].length)return this._buffers.shift();if(e=r.length?t.set(this._buffers.shift(),i):(t.set(new Uint8Array(r.buffer,r.byteOffset,e),i),this._buffers[0]=new tr(r.buffer,r.byteOffset+e,r.length-e)),e-=r.length}while(e>0);return t}startLoop(e){this._loop=!0;do switch(this._state){case ne:this.getInfo(e);break;case Zs:this.getPayloadLength16(e);break;case Ys:this.getPayloadLength64(e);break;case Xs:this.getMask();break;case un:this.getData(e);break;case cn:case rr:this._loop=!1;return}while(this._loop);this._errored||e()}getInfo(e){if(this._bufferedBytes<2){this._loop=!1;return}let t=this.consume(2);if((t[0]&48)!==0){let i=this.createError(RangeError,"RSV2 and RSV3 must be clear",!0,1002,"WS_ERR_UNEXPECTED_RSV_2_3");e(i);return}let r=(t[0]&64)===64;if(r&&!this._extensions[$s.extensionName]){let i=this.createError(RangeError,"RSV1 must be clear",!0,1002,"WS_ERR_UNEXPECTED_RSV_1");e(i);return}if(this._fin=(t[0]&128)===128,this._opcode=t[0]&15,this._payloadLength=t[1]&127,this._opcode===0){if(r){let i=this.createError(RangeError,"RSV1 must be clear",!0,1002,"WS_ERR_UNEXPECTED_RSV_1");e(i);return}if(!this._fragmented){let i=this.createError(RangeError,"invalid opcode 0",!0,1002,"WS_ERR_INVALID_OPCODE");e(i);return}this._opcode=this._fragmented}else if(this._opcode===1||this._opcode===2){if(this._fragmented){let i=this.createError(RangeError,`invalid opcode ${this._opcode}`,!0,1002,"WS_ERR_INVALID_OPCODE");e(i);return}this._compressed=r}else if(this._opcode>7&&this._opcode<11){if(!this._fin){let i=this.createError(RangeError,"FIN must be set",!0,1002,"WS_ERR_EXPECTED_FIN");e(i);return}if(r){let i=this.createError(RangeError,"RSV1 must be clear",!0,1002,"WS_ERR_UNEXPECTED_RSV_1");e(i);return}if(this._payloadLength>125||this._opcode===8&&this._payloadLength===1){let i=this.createError(RangeError,`invalid payload length ${this._payloadLength}`,!0,1002,"WS_ERR_INVALID_CONTROL_PAYLOAD_LENGTH");e(i);return}}else{let i=this.createError(RangeError,`invalid opcode ${this._opcode}`,!0,1002,"WS_ERR_INVALID_OPCODE");e(i);return}if(!this._fin&&!this._fragmented&&(this._fragmented=this._opcode),this._masked=(t[1]&128)===128,this._isServer){if(!this._masked){let i=this.createError(RangeError,"MASK must be set",!0,1002,"WS_ERR_EXPECTED_MASK");e(i);return}}else if(this._masked){let i=this.createError(RangeError,"MASK must be clear",!0,1002,"WS_ERR_UNEXPECTED_MASK");e(i);return}this._payloadLength===126?this._state=Zs:this._payloadLength===127?this._state=Ys:this.haveLength(e)}getPayloadLength16(e){if(this._bufferedBytes<2){this._loop=!1;return}this._payloadLength=this.consume(2).readUInt16BE(0),this.haveLength(e)}getPayloadLength64(e){if(this._bufferedBytes<8){this._loop=!1;return}let t=this.consume(8),r=t.readUInt32BE(0);if(r>Math.pow(2,21)-1){let i=this.createError(RangeError,"Unsupported WebSocket frame: payload length > 2^53 - 1",!1,1009,"WS_ERR_UNSUPPORTED_DATA_PAYLOAD_LENGTH");e(i);return}this._payloadLength=r*Math.pow(2,32)+t.readUInt32BE(4),this.haveLength(e)}haveLength(e){if(this._payloadLength&&this._opcode<8&&(this._totalPayloadLength+=this._payloadLength,this._totalPayloadLength>this._maxPayload&&this._maxPayload>0)){let t=this.createError(RangeError,"Max payload size exceeded",!1,1009,"WS_ERR_UNSUPPORTED_MESSAGE_LENGTH");e(t);return}this._masked?this._state=Xs:this._state=un}getMask(){if(this._bufferedBytes<4){this._loop=!1;return}this._mask=this.consume(4),this._state=un}getData(e){let t=Vs;if(this._payloadLength){if(this._bufferedBytes7){this.controlMessage(t,e);return}if(this._compressed){this._state=cn,this.decompress(t,e);return}t.length&&(this._messageLength=this._totalPayloadLength,this._fragments.push(t)),this.dataMessage(e)}decompress(e,t){this._extensions[$s.extensionName].decompress(e,this._fin,(i,s)=>{if(i)return t(i);if(s.length){if(this._messageLength+=s.length,this._messageLength>this._maxPayload&&this._maxPayload>0){let o=this.createError(RangeError,"Max payload size exceeded",!1,1009,"WS_ERR_UNSUPPORTED_MESSAGE_LENGTH");t(o);return}this._fragments.push(s)}this.dataMessage(t),this._state===ne&&this.startLoop(t)})}dataMessage(e){if(!this._fin){this._state=ne;return}let t=this._messageLength,r=this._fragments;if(this._totalPayloadLength=0,this._messageLength=0,this._fragmented=0,this._fragments=[],this._opcode===2){let i;this._binaryType==="nodebuffer"?i=fn(r,t):this._binaryType==="arraybuffer"?i=Vf(fn(r,t)):this._binaryType==="blob"?i=new Blob(r):i=r,this._allowSynchronousEvents?(this.emit("message",i,!0),this._state=ne):(this._state=rr,setImmediate(()=>{this.emit("message",i,!0),this._state=ne,this.startLoop(e)}))}else{let i=fn(r,t);if(!this._skipUTF8Validation&&!Hs(i)){let s=this.createError(Error,"invalid UTF-8 sequence",!0,1007,"WS_ERR_INVALID_UTF8");e(s);return}this._state===cn||this._allowSynchronousEvents?(this.emit("message",i,!1),this._state=ne):(this._state=rr,setImmediate(()=>{this.emit("message",i,!1),this._state=ne,this.startLoop(e)}))}}controlMessage(e,t){if(this._opcode===8){if(e.length===0)this._loop=!1,this.emit("conclude",1005,Vs),this.end();else{let r=e.readUInt16BE(0);if(!Zf(r)){let s=this.createError(RangeError,`invalid status code ${r}`,!0,1002,"WS_ERR_INVALID_CLOSE_CODE");t(s);return}let i=new tr(e.buffer,e.byteOffset+2,e.length-2);if(!this._skipUTF8Validation&&!Hs(i)){let s=this.createError(Error,"invalid UTF-8 sequence",!0,1007,"WS_ERR_INVALID_UTF8");t(s);return}this._loop=!1,this.emit("conclude",r,i),this.end()}this._state=ne;return}this._allowSynchronousEvents?(this.emit(this._opcode===9?"ping":"pong",e),this._state=ne):(this._state=rr,setImmediate(()=>{this.emit(this._opcode===9?"ping":"pong",e),this._state=ne,this.startLoop(t)}))}createError(e,t,r,i,s){this._loop=!1,this._errored=!0;let o=new e(r?`Invalid WebSocket frame: ${t}`:t);return Error.captureStackTrace(o,this.createError),o.code=s,o[jf]=i,o}};Ks.exports=hn});var gn=b((id,eo)=>{"use strict";var{Duplex:nd}=require("stream"),{randomFillSync:Yf}=require("crypto"),Js=xt(),{EMPTY_BUFFER:Xf,kWebSocket:Kf,NOOP:Jf}=we(),{isBlob:Qe,isValidStatusCode:Qf}=Je(),{mask:Qs,toBuffer:Ue}=St(),ie=Symbol("kByteLength"),eu=Buffer.alloc(4),nr=8*1024,ke,et=nr,de=0,tu=1,ru=2,pn=class n{constructor(e,t,r){this._extensions=t||{},r&&(this._generateMask=r,this._maskBuffer=Buffer.alloc(4)),this._socket=e,this._firstFragment=!0,this._compress=!1,this._bufferedBytes=0,this._queue=[],this._state=de,this.onerror=Jf,this[Kf]=void 0}static frame(e,t){let r,i=!1,s=2,o=!1;t.mask&&(r=t.maskBuffer||eu,t.generateMask?t.generateMask(r):(et===nr&&(ke===void 0&&(ke=Buffer.alloc(nr)),Yf(ke,0,nr),et=0),r[0]=ke[et++],r[1]=ke[et++],r[2]=ke[et++],r[3]=ke[et++]),o=(r[0]|r[1]|r[2]|r[3])===0,s=6);let a;typeof e=="string"?(!t.mask||o)&&t[ie]!==void 0?a=t[ie]:(e=Buffer.from(e),a=e.length):(a=e.length,i=t.mask&&t.readOnly&&!o);let l=a;a>=65536?(s+=8,l=127):a>125&&(s+=2,l=126);let f=Buffer.allocUnsafe(i?a+s:s);return f[0]=t.fin?t.opcode|128:t.opcode,t.rsv1&&(f[0]|=64),f[1]=l,l===126?f.writeUInt16BE(a,2):l===127&&(f[2]=f[3]=0,f.writeUIntBE(a,4,6)),t.mask?(f[1]|=128,f[s-4]=r[0],f[s-3]=r[1],f[s-2]=r[2],f[s-1]=r[3],o?[f,e]:i?(Qs(e,r,f,s,a),[f]):(Qs(e,r,e,0,a),[f,e])):[f,e]}close(e,t,r,i){let s;if(e===void 0)s=Xf;else{if(typeof e!="number"||!Qf(e))throw new TypeError("First argument must be a valid error code number");if(t===void 0||!t.length)s=Buffer.allocUnsafe(2),s.writeUInt16BE(e,0);else{let a=Buffer.byteLength(t);if(a>123)throw new RangeError("The message must not be greater than 123 bytes");s=Buffer.allocUnsafe(2+a),s.writeUInt16BE(e,0),typeof t=="string"?s.write(t,2):s.set(t,2)}}let o={[ie]:s.length,fin:!0,generateMask:this._generateMask,mask:r,maskBuffer:this._maskBuffer,opcode:8,readOnly:!1,rsv1:!1};this._state!==de?this.enqueue([this.dispatch,s,!1,o,i]):this.sendFrame(n.frame(s,o),i)}ping(e,t,r){let i,s;if(typeof e=="string"?(i=Buffer.byteLength(e),s=!1):Qe(e)?(i=e.size,s=!1):(e=Ue(e),i=e.length,s=Ue.readOnly),i>125)throw new RangeError("The data size must not be greater than 125 bytes");let o={[ie]:i,fin:!0,generateMask:this._generateMask,mask:t,maskBuffer:this._maskBuffer,opcode:9,readOnly:s,rsv1:!1};Qe(e)?this._state!==de?this.enqueue([this.getBlobData,e,!1,o,r]):this.getBlobData(e,!1,o,r):this._state!==de?this.enqueue([this.dispatch,e,!1,o,r]):this.sendFrame(n.frame(e,o),r)}pong(e,t,r){let i,s;if(typeof e=="string"?(i=Buffer.byteLength(e),s=!1):Qe(e)?(i=e.size,s=!1):(e=Ue(e),i=e.length,s=Ue.readOnly),i>125)throw new RangeError("The data size must not be greater than 125 bytes");let o={[ie]:i,fin:!0,generateMask:this._generateMask,mask:t,maskBuffer:this._maskBuffer,opcode:10,readOnly:s,rsv1:!1};Qe(e)?this._state!==de?this.enqueue([this.getBlobData,e,!1,o,r]):this.getBlobData(e,!1,o,r):this._state!==de?this.enqueue([this.dispatch,e,!1,o,r]):this.sendFrame(n.frame(e,o),r)}send(e,t,r){let i=this._extensions[Js.extensionName],s=t.binary?2:1,o=t.compress,a,l;typeof e=="string"?(a=Buffer.byteLength(e),l=!1):Qe(e)?(a=e.size,l=!1):(e=Ue(e),a=e.length,l=Ue.readOnly),this._firstFragment?(this._firstFragment=!1,o&&i&&i.params[i._isServer?"server_no_context_takeover":"client_no_context_takeover"]&&(o=a>=i._threshold),this._compress=o):(o=!1,s=0),t.fin&&(this._firstFragment=!0);let f={[ie]:a,fin:t.fin,generateMask:this._generateMask,mask:t.mask,maskBuffer:this._maskBuffer,opcode:s,readOnly:l,rsv1:o};Qe(e)?this._state!==de?this.enqueue([this.getBlobData,e,this._compress,f,r]):this.getBlobData(e,this._compress,f,r):this._state!==de?this.enqueue([this.dispatch,e,this._compress,f,r]):this.dispatch(e,this._compress,f,r)}getBlobData(e,t,r,i){this._bufferedBytes+=r[ie],this._state=ru,e.arrayBuffer().then(s=>{if(this._socket.destroyed){let a=new Error("The socket was closed while the blob was being read");process.nextTick(mn,this,a,i);return}this._bufferedBytes-=r[ie];let o=Ue(s);t?this.dispatch(o,t,r,i):(this._state=de,this.sendFrame(n.frame(o,r),i),this.dequeue())}).catch(s=>{process.nextTick(nu,this,s,i)})}dispatch(e,t,r,i){if(!t){this.sendFrame(n.frame(e,r),i);return}let s=this._extensions[Js.extensionName];this._bufferedBytes+=r[ie],this._state=tu,s.compress(e,r.fin,(o,a)=>{if(this._socket.destroyed){let l=new Error("The socket was closed while data was being compressed");mn(this,l,i);return}this._bufferedBytes-=r[ie],this._state=de,r.readOnly=!1,this.sendFrame(n.frame(a,r),i),this.dequeue()})}dequeue(){for(;this._state===de&&this._queue.length;){let e=this._queue.shift();this._bufferedBytes-=e[3][ie],Reflect.apply(e[0],this,e.slice(1))}}enqueue(e){this._bufferedBytes+=e[3][ie],this._queue.push(e)}sendFrame(e,t){e.length===2?(this._socket.cork(),this._socket.write(e[0]),this._socket.write(e[1],t),this._socket.uncork()):this._socket.write(e[0],t)}};eo.exports=pn;function mn(n,e,t){typeof t=="function"&&t(e);for(let r=0;r{"use strict";var{kForOnEventAttribute:Ct,kListener:_n}=we(),to=Symbol("kCode"),ro=Symbol("kData"),no=Symbol("kError"),io=Symbol("kMessage"),so=Symbol("kReason"),tt=Symbol("kTarget"),oo=Symbol("kType"),lo=Symbol("kWasClean"),Se=class{constructor(e){this[tt]=null,this[oo]=e}get target(){return this[tt]}get type(){return this[oo]}};Object.defineProperty(Se.prototype,"target",{enumerable:!0});Object.defineProperty(Se.prototype,"type",{enumerable:!0});var Be=class extends Se{constructor(e,t={}){super(e),this[to]=t.code===void 0?0:t.code,this[so]=t.reason===void 0?"":t.reason,this[lo]=t.wasClean===void 0?!1:t.wasClean}get code(){return this[to]}get reason(){return this[so]}get wasClean(){return this[lo]}};Object.defineProperty(Be.prototype,"code",{enumerable:!0});Object.defineProperty(Be.prototype,"reason",{enumerable:!0});Object.defineProperty(Be.prototype,"wasClean",{enumerable:!0});var rt=class extends Se{constructor(e,t={}){super(e),this[no]=t.error===void 0?null:t.error,this[io]=t.message===void 0?"":t.message}get error(){return this[no]}get message(){return this[io]}};Object.defineProperty(rt.prototype,"error",{enumerable:!0});Object.defineProperty(rt.prototype,"message",{enumerable:!0});var bt=class extends Se{constructor(e,t={}){super(e),this[ro]=t.data===void 0?null:t.data}get data(){return this[ro]}};Object.defineProperty(bt.prototype,"data",{enumerable:!0});var iu={addEventListener(n,e,t={}){for(let i of this.listeners(n))if(!t[Ct]&&i[_n]===e&&!i[Ct])return;let r;if(n==="message")r=function(s,o){let a=new bt("message",{data:o?s:s.toString()});a[tt]=this,ir(e,this,a)};else if(n==="close")r=function(s,o){let a=new Be("close",{code:s,reason:o.toString(),wasClean:this._closeFrameReceived&&this._closeFrameSent});a[tt]=this,ir(e,this,a)};else if(n==="error")r=function(s){let o=new rt("error",{error:s,message:s.message});o[tt]=this,ir(e,this,o)};else if(n==="open")r=function(){let s=new Se("open");s[tt]=this,ir(e,this,s)};else return;r[Ct]=!!t[Ct],r[_n]=e,t.once?this.once(n,r):this.on(n,r)},removeEventListener(n,e){for(let t of this.listeners(n))if(t[_n]===e&&!t[Ct]){this.removeListener(n,t);break}}};ao.exports={CloseEvent:Be,ErrorEvent:rt,Event:Se,EventTarget:iu,MessageEvent:bt};function ir(n,e,t){typeof n=="object"&&n.handleEvent?n.handleEvent.call(n,t):n.call(e,t)}});var En=b((od,uo)=>{"use strict";var{tokenChars:Lt}=Je();function me(n,e,t){n[e]===void 0?n[e]=[t]:n[e].push(t)}function su(n){let e=Object.create(null),t=Object.create(null),r=!1,i=!1,s=!1,o,a,l=-1,f=-1,u=-1,h=0;for(;h{let t=n[e];return Array.isArray(t)||(t=[t]),t.map(r=>[e].concat(Object.keys(r).map(i=>{let s=r[i];return Array.isArray(s)||(s=[s]),s.map(o=>o===!0?i:`${i}=${o}`).join("; ")})).join("; ")).join(", ")}).join(", ")}uo.exports={format:ou,parse:su}});var ar=b((fd,xo)=>{"use strict";var lu=require("events"),au=require("https"),fu=require("http"),po=require("net"),uu=require("tls"),{randomBytes:cu,createHash:hu}=require("crypto"),{Duplex:ld,Readable:ad}=require("stream"),{URL:wn}=require("url"),Le=xt(),du=dn(),pu=gn(),{isBlob:mu}=Je(),{BINARY_TYPES:co,EMPTY_BUFFER:sr,GUID:gu,kForOnEventAttribute:yn,kListener:_u,kStatusCode:Eu,kWebSocket:V,NOOP:mo}=we(),{EventTarget:{addEventListener:wu,removeEventListener:yu}}=fo(),{format:Su,parse:vu}=En(),{toBuffer:xu}=St(),Cu=30*1e3,go=Symbol("kAborted"),Sn=[8,13],ve=["CONNECTING","OPEN","CLOSING","CLOSED"],bu=/^[!#$%&'*+\-.0-9A-Z^_`|a-z~]+$/,U=class n extends lu{constructor(e,t,r){super(),this._binaryType=co[0],this._closeCode=1006,this._closeFrameReceived=!1,this._closeFrameSent=!1,this._closeMessage=sr,this._closeTimer=null,this._errorEmitted=!1,this._extensions={},this._paused=!1,this._protocol="",this._readyState=n.CONNECTING,this._receiver=null,this._sender=null,this._socket=null,e!==null?(this._bufferedAmount=0,this._isServer=!1,this._redirects=0,t===void 0?t=[]:Array.isArray(t)||(typeof t=="object"&&t!==null?(r=t,t=[]):t=[t]),_o(this,e,t,r)):(this._autoPong=r.autoPong,this._isServer=!0)}get binaryType(){return this._binaryType}set binaryType(e){co.includes(e)&&(this._binaryType=e,this._receiver&&(this._receiver._binaryType=e))}get bufferedAmount(){return this._socket?this._socket._writableState.length+this._sender._bufferedBytes:this._bufferedAmount}get extensions(){return Object.keys(this._extensions).join()}get isPaused(){return this._paused}get onclose(){return null}get onerror(){return null}get onopen(){return null}get onmessage(){return null}get protocol(){return this._protocol}get readyState(){return this._readyState}get url(){return this._url}setSocket(e,t,r){let i=new du({allowSynchronousEvents:r.allowSynchronousEvents,binaryType:this.binaryType,extensions:this._extensions,isServer:this._isServer,maxPayload:r.maxPayload,skipUTF8Validation:r.skipUTF8Validation}),s=new pu(e,this._extensions,r.generateMask);this._receiver=i,this._sender=s,this._socket=e,i[V]=this,s[V]=this,e[V]=this,i.on("conclude",Iu),i.on("drain",Nu),i.on("error",Tu),i.on("message",Ru),i.on("ping",Au),i.on("pong",Du),s.onerror=Mu,e.setTimeout&&e.setTimeout(0),e.setNoDelay&&e.setNoDelay(),t.length>0&&e.unshift(t),e.on("close",yo),e.on("data",lr),e.on("end",So),e.on("error",vo),this._readyState=n.OPEN,this.emit("open")}emitClose(){if(!this._socket){this._readyState=n.CLOSED,this.emit("close",this._closeCode,this._closeMessage);return}this._extensions[Le.extensionName]&&this._extensions[Le.extensionName].cleanup(),this._receiver.removeAllListeners(),this._readyState=n.CLOSED,this.emit("close",this._closeCode,this._closeMessage)}close(e,t){if(this.readyState!==n.CLOSED){if(this.readyState===n.CONNECTING){ee(this,this._req,"WebSocket was closed before the connection was established");return}if(this.readyState===n.CLOSING){this._closeFrameSent&&(this._closeFrameReceived||this._receiver._writableState.errorEmitted)&&this._socket.end();return}this._readyState=n.CLOSING,this._sender.close(e,t,!this._isServer,r=>{r||(this._closeFrameSent=!0,(this._closeFrameReceived||this._receiver._writableState.errorEmitted)&&this._socket.end())}),wo(this)}}pause(){this.readyState===n.CONNECTING||this.readyState===n.CLOSED||(this._paused=!0,this._socket.pause())}ping(e,t,r){if(this.readyState===n.CONNECTING)throw new Error("WebSocket is not open: readyState 0 (CONNECTING)");if(typeof e=="function"?(r=e,e=t=void 0):typeof t=="function"&&(r=t,t=void 0),typeof e=="number"&&(e=e.toString()),this.readyState!==n.OPEN){vn(this,e,r);return}t===void 0&&(t=!this._isServer),this._sender.ping(e||sr,t,r)}pong(e,t,r){if(this.readyState===n.CONNECTING)throw new Error("WebSocket is not open: readyState 0 (CONNECTING)");if(typeof e=="function"?(r=e,e=t=void 0):typeof t=="function"&&(r=t,t=void 0),typeof e=="number"&&(e=e.toString()),this.readyState!==n.OPEN){vn(this,e,r);return}t===void 0&&(t=!this._isServer),this._sender.pong(e||sr,t,r)}resume(){this.readyState===n.CONNECTING||this.readyState===n.CLOSED||(this._paused=!1,this._receiver._writableState.needDrain||this._socket.resume())}send(e,t,r){if(this.readyState===n.CONNECTING)throw new Error("WebSocket is not open: readyState 0 (CONNECTING)");if(typeof t=="function"&&(r=t,t={}),typeof e=="number"&&(e=e.toString()),this.readyState!==n.OPEN){vn(this,e,r);return}let i={binary:typeof e!="string",mask:!this._isServer,compress:!0,fin:!0,...t};this._extensions[Le.extensionName]||(i.compress=!1),this._sender.send(e||sr,i,r)}terminate(){if(this.readyState!==n.CLOSED){if(this.readyState===n.CONNECTING){ee(this,this._req,"WebSocket was closed before the connection was established");return}this._socket&&(this._readyState=n.CLOSING,this._socket.destroy())}}};Object.defineProperty(U,"CONNECTING",{enumerable:!0,value:ve.indexOf("CONNECTING")});Object.defineProperty(U.prototype,"CONNECTING",{enumerable:!0,value:ve.indexOf("CONNECTING")});Object.defineProperty(U,"OPEN",{enumerable:!0,value:ve.indexOf("OPEN")});Object.defineProperty(U.prototype,"OPEN",{enumerable:!0,value:ve.indexOf("OPEN")});Object.defineProperty(U,"CLOSING",{enumerable:!0,value:ve.indexOf("CLOSING")});Object.defineProperty(U.prototype,"CLOSING",{enumerable:!0,value:ve.indexOf("CLOSING")});Object.defineProperty(U,"CLOSED",{enumerable:!0,value:ve.indexOf("CLOSED")});Object.defineProperty(U.prototype,"CLOSED",{enumerable:!0,value:ve.indexOf("CLOSED")});["binaryType","bufferedAmount","extensions","isPaused","protocol","readyState","url"].forEach(n=>{Object.defineProperty(U.prototype,n,{enumerable:!0})});["open","error","close","message"].forEach(n=>{Object.defineProperty(U.prototype,`on${n}`,{enumerable:!0,get(){for(let e of this.listeners(n))if(e[yn])return e[_u];return null},set(e){for(let t of this.listeners(n))if(t[yn]){this.removeListener(n,t);break}typeof e=="function"&&this.addEventListener(n,e,{[yn]:!0})}})});U.prototype.addEventListener=wu;U.prototype.removeEventListener=yu;xo.exports=U;function _o(n,e,t,r){let i={allowSynchronousEvents:!0,autoPong:!0,protocolVersion:Sn[1],maxPayload:104857600,skipUTF8Validation:!1,perMessageDeflate:!0,followRedirects:!1,maxRedirects:10,...r,socketPath:void 0,hostname:void 0,protocol:void 0,timeout:void 0,method:"GET",host:void 0,path:void 0,port:void 0};if(n._autoPong=i.autoPong,!Sn.includes(i.protocolVersion))throw new RangeError(`Unsupported protocol version: ${i.protocolVersion} (supported versions: ${Sn.join(", ")})`);let s;if(e instanceof wn)s=e;else try{s=new wn(e)}catch{throw new SyntaxError(`Invalid URL: ${e}`)}s.protocol==="http:"?s.protocol="ws:":s.protocol==="https:"&&(s.protocol="wss:"),n._url=s.href;let o=s.protocol==="wss:",a=s.protocol==="ws+unix:",l;if(s.protocol!=="ws:"&&!o&&!a?l=`The URL's protocol must be one of "ws:", "wss:", "http:", "https:", or "ws+unix:"`:a&&!s.pathname?l="The URL's pathname is empty":s.hash&&(l="The URL contains a fragment identifier"),l){let p=new SyntaxError(l);if(n._redirects===0)throw p;or(n,p);return}let f=o?443:80,u=cu(16).toString("base64"),h=o?au.request:fu.request,c=new Set,d;if(i.createConnection=i.createConnection||(o?Ou:Lu),i.defaultPort=i.defaultPort||f,i.port=s.port||f,i.host=s.hostname.startsWith("[")?s.hostname.slice(1,-1):s.hostname,i.headers={...i.headers,"Sec-WebSocket-Version":i.protocolVersion,"Sec-WebSocket-Key":u,Connection:"Upgrade",Upgrade:"websocket"},i.path=s.pathname+s.search,i.timeout=i.handshakeTimeout,i.perMessageDeflate&&(d=new Le(i.perMessageDeflate!==!0?i.perMessageDeflate:{},!1,i.maxPayload),i.headers["Sec-WebSocket-Extensions"]=Su({[Le.extensionName]:d.offer()})),t.length){for(let p of t){if(typeof p!="string"||!bu.test(p)||c.has(p))throw new SyntaxError("An invalid or duplicated subprotocol was specified");c.add(p)}i.headers["Sec-WebSocket-Protocol"]=t.join(",")}if(i.origin&&(i.protocolVersion<13?i.headers["Sec-WebSocket-Origin"]=i.origin:i.headers.Origin=i.origin),(s.username||s.password)&&(i.auth=`${s.username}:${s.password}`),a){let p=i.path.split(":");i.socketPath=p[0],i.path=p[1]}let m;if(i.followRedirects){if(n._redirects===0){n._originalIpc=a,n._originalSecure=o,n._originalHostOrSocketPath=a?i.socketPath:s.host;let p=r&&r.headers;if(r={...r,headers:{}},p)for(let[_,v]of Object.entries(p))r.headers[_.toLowerCase()]=v}else if(n.listenerCount("redirect")===0){let p=a?n._originalIpc?i.socketPath===n._originalHostOrSocketPath:!1:n._originalIpc?!1:s.host===n._originalHostOrSocketPath;(!p||n._originalSecure&&!o)&&(delete i.headers.authorization,delete i.headers.cookie,p||delete i.headers.host,i.auth=void 0)}i.auth&&!r.headers.authorization&&(r.headers.authorization="Basic "+Buffer.from(i.auth).toString("base64")),m=n._req=h(i),n._redirects&&n.emit("redirect",n.url,m)}else m=n._req=h(i);i.timeout&&m.on("timeout",()=>{ee(n,m,"Opening handshake has timed out")}),m.on("error",p=>{m===null||m[go]||(m=n._req=null,or(n,p))}),m.on("response",p=>{let _=p.headers.location,v=p.statusCode;if(_&&i.followRedirects&&v>=300&&v<400){if(++n._redirects>i.maxRedirects){ee(n,m,"Maximum redirects exceeded");return}m.abort();let C;try{C=new wn(_,e)}catch{let L=new SyntaxError(`Invalid URL: ${_}`);or(n,L);return}_o(n,C,t,r)}else n.emit("unexpected-response",m,p)||ee(n,m,`Unexpected server response: ${p.statusCode}`)}),m.on("upgrade",(p,_,v)=>{if(n.emit("upgrade",p),n.readyState!==U.CONNECTING)return;m=n._req=null;let C=p.headers.upgrade;if(C===void 0||C.toLowerCase()!=="websocket"){ee(n,_,"Invalid Upgrade header");return}let I=hu("sha1").update(u+gu).digest("base64");if(p.headers["sec-websocket-accept"]!==I){ee(n,_,"Invalid Sec-WebSocket-Accept header");return}let L=p.headers["sec-websocket-protocol"],R;if(L!==void 0?c.size?c.has(L)||(R="Server sent an invalid subprotocol"):R="Server sent a subprotocol but none was requested":c.size&&(R="Server sent no subprotocol"),R){ee(n,_,R);return}L&&(n._protocol=L);let O=p.headers["sec-websocket-extensions"];if(O!==void 0){if(!d){ee(n,_,"Server sent a Sec-WebSocket-Extensions header but no extension was requested");return}let B;try{B=vu(O)}catch{ee(n,_,"Invalid Sec-WebSocket-Extensions header");return}let P=Object.keys(B);if(P.length!==1||P[0]!==Le.extensionName){ee(n,_,"Server indicated an extension that was not requested");return}try{d.accept(B[Le.extensionName])}catch{ee(n,_,"Invalid Sec-WebSocket-Extensions header");return}n._extensions[Le.extensionName]=d}n.setSocket(_,v,{allowSynchronousEvents:i.allowSynchronousEvents,generateMask:i.generateMask,maxPayload:i.maxPayload,skipUTF8Validation:i.skipUTF8Validation})}),i.finishRequest?i.finishRequest(m,n):m.end()}function or(n,e){n._readyState=U.CLOSING,n._errorEmitted=!0,n.emit("error",e),n.emitClose()}function Lu(n){return n.path=n.socketPath,po.connect(n)}function Ou(n){return n.path=void 0,!n.servername&&n.servername!==""&&(n.servername=po.isIP(n.host)?"":n.host),uu.connect(n)}function ee(n,e,t){n._readyState=U.CLOSING;let r=new Error(t);Error.captureStackTrace(r,ee),e.setHeader?(e[go]=!0,e.abort(),e.socket&&!e.socket.destroyed&&e.socket.destroy(),process.nextTick(or,n,r)):(e.destroy(r),e.once("error",n.emit.bind(n,"error")),e.once("close",n.emitClose.bind(n)))}function vn(n,e,t){if(e){let r=mu(e)?e.size:xu(e).length;n._socket?n._sender._bufferedBytes+=r:n._bufferedAmount+=r}if(t){let r=new Error(`WebSocket is not open: readyState ${n.readyState} (${ve[n.readyState]})`);process.nextTick(t,r)}}function Iu(n,e){let t=this[V];t._closeFrameReceived=!0,t._closeMessage=e,t._closeCode=n,t._socket[V]!==void 0&&(t._socket.removeListener("data",lr),process.nextTick(Eo,t._socket),n===1005?t.close():t.close(n,e))}function Nu(){let n=this[V];n.isPaused||n._socket.resume()}function Tu(n){let e=this[V];e._socket[V]!==void 0&&(e._socket.removeListener("data",lr),process.nextTick(Eo,e._socket),e.close(n[Eu])),e._errorEmitted||(e._errorEmitted=!0,e.emit("error",n))}function ho(){this[V].emitClose()}function Ru(n,e){this[V].emit("message",n,e)}function Au(n){let e=this[V];e._autoPong&&e.pong(n,!this._isServer,mo),e.emit("ping",n)}function Du(n){this[V].emit("pong",n)}function Eo(n){n.resume()}function Mu(n){let e=this[V];e.readyState!==U.CLOSED&&(e.readyState===U.OPEN&&(e._readyState=U.CLOSING,wo(e)),this._socket.end(),e._errorEmitted||(e._errorEmitted=!0,e.emit("error",n)))}function wo(n){n._closeTimer=setTimeout(n._socket.destroy.bind(n._socket),Cu)}function yo(){let n=this[V];this.removeListener("close",yo),this.removeListener("data",lr),this.removeListener("end",So),n._readyState=U.CLOSING;let e;!this._readableState.endEmitted&&!n._closeFrameReceived&&!n._receiver._writableState.errorEmitted&&(e=n._socket.read())!==null&&n._receiver.write(e),n._receiver.end(),this[V]=void 0,clearTimeout(n._closeTimer),n._receiver._writableState.finished||n._receiver._writableState.errorEmitted?n.emitClose():(n._receiver.on("error",ho),n._receiver.on("finish",ho))}function lr(n){this[V]._receiver.write(n)||this.pause()}function So(){let n=this[V];n._readyState=U.CLOSING,n._receiver.end(),this.end()}function vo(){let n=this[V];this.removeListener("error",vo),this.on("error",mo),n&&(n._readyState=U.CLOSING,this.destroy())}});var Oo=b((cd,Lo)=>{"use strict";var ud=ar(),{Duplex:Pu}=require("stream");function Co(n){n.emit("close")}function Fu(){!this.destroyed&&this._writableState.finished&&this.destroy()}function bo(n){this.removeListener("error",bo),this.destroy(),this.listenerCount("error")===0&&this.emit("error",n)}function Uu(n,e){let t=!0,r=new Pu({...e,autoDestroy:!1,emitClose:!1,objectMode:!1,writableObjectMode:!1});return n.on("message",function(s,o){let a=!o&&r._readableState.objectMode?s.toString():s;r.push(a)||n.pause()}),n.once("error",function(s){r.destroyed||(t=!1,r.destroy(s))}),n.once("close",function(){r.destroyed||r.push(null)}),r._destroy=function(i,s){if(n.readyState===n.CLOSED){s(i),process.nextTick(Co,r);return}let o=!1;n.once("error",function(l){o=!0,s(l)}),n.once("close",function(){o||s(i),process.nextTick(Co,r)}),t&&n.terminate()},r._final=function(i){if(n.readyState===n.CONNECTING){n.once("open",function(){r._final(i)});return}n._socket!==null&&(n._socket._writableState.finished?(i(),r._readableState.endEmitted&&r.destroy()):(n._socket.once("finish",function(){i()}),n.close()))},r._read=function(){n.isPaused&&n.resume()},r._write=function(i,s,o){if(n.readyState===n.CONNECTING){n.once("open",function(){r._write(i,s,o)});return}n.send(i,o)},r.on("end",Fu),r.on("error",bo),r}Lo.exports=Uu});var No=b((hd,Io)=>{"use strict";var{tokenChars:ku}=Je();function Bu(n){let e=new Set,t=-1,r=-1,i=0;for(i;i{"use strict";var zu=require("events"),fr=require("http"),{Duplex:dd}=require("stream"),{createHash:Gu}=require("crypto"),To=En(),ze=xt(),Wu=No(),qu=ar(),{GUID:ju,kWebSocket:$u}=we(),Vu=/^[+/0-9A-Za-z]{22}==$/,Ro=0,Ao=1,Mo=2,xn=class extends zu{constructor(e,t){if(super(),e={allowSynchronousEvents:!0,autoPong:!0,maxPayload:100*1024*1024,skipUTF8Validation:!1,perMessageDeflate:!1,handleProtocols:null,clientTracking:!0,verifyClient:null,noServer:!1,backlog:null,server:null,host:null,path:null,port:null,WebSocket:qu,...e},e.port==null&&!e.server&&!e.noServer||e.port!=null&&(e.server||e.noServer)||e.server&&e.noServer)throw new TypeError('One and only one of the "port", "server", or "noServer" options must be specified');if(e.port!=null?(this._server=fr.createServer((r,i)=>{let s=fr.STATUS_CODES[426];i.writeHead(426,{"Content-Length":s.length,"Content-Type":"text/plain"}),i.end(s)}),this._server.listen(e.port,e.host,e.backlog,t)):e.server&&(this._server=e.server),this._server){let r=this.emit.bind(this,"connection");this._removeListeners=Hu(this._server,{listening:this.emit.bind(this,"listening"),error:this.emit.bind(this,"error"),upgrade:(i,s,o)=>{this.handleUpgrade(i,s,o,r)}})}e.perMessageDeflate===!0&&(e.perMessageDeflate={}),e.clientTracking&&(this.clients=new Set,this._shouldEmitClose=!1),this.options=e,this._state=Ro}address(){if(this.options.noServer)throw new Error('The server is operating in "noServer" mode');return this._server?this._server.address():null}close(e){if(this._state===Mo){e&&this.once("close",()=>{e(new Error("The server is not running"))}),process.nextTick(Ot,this);return}if(e&&this.once("close",e),this._state!==Ao)if(this._state=Ao,this.options.noServer||this.options.server)this._server&&(this._removeListeners(),this._removeListeners=this._server=null),this.clients?this.clients.size?this._shouldEmitClose=!0:process.nextTick(Ot,this):process.nextTick(Ot,this);else{let t=this._server;this._removeListeners(),this._removeListeners=this._server=null,t.close(()=>{Ot(this)})}}shouldHandle(e){if(this.options.path){let t=e.url.indexOf("?");if((t!==-1?e.url.slice(0,t):e.url)!==this.options.path)return!1}return!0}handleUpgrade(e,t,r,i){t.on("error",Do);let s=e.headers["sec-websocket-key"],o=e.headers.upgrade,a=+e.headers["sec-websocket-version"];if(e.method!=="GET"){Ge(this,e,t,405,"Invalid HTTP method");return}if(o===void 0||o.toLowerCase()!=="websocket"){Ge(this,e,t,400,"Invalid Upgrade header");return}if(s===void 0||!Vu.test(s)){Ge(this,e,t,400,"Missing or invalid Sec-WebSocket-Key header");return}if(a!==13&&a!==8){Ge(this,e,t,400,"Missing or invalid Sec-WebSocket-Version header",{"Sec-WebSocket-Version":"13, 8"});return}if(!this.shouldHandle(e)){It(t,400);return}let l=e.headers["sec-websocket-protocol"],f=new Set;if(l!==void 0)try{f=Wu.parse(l)}catch{Ge(this,e,t,400,"Invalid Sec-WebSocket-Protocol header");return}let u=e.headers["sec-websocket-extensions"],h={};if(this.options.perMessageDeflate&&u!==void 0){let c=new ze(this.options.perMessageDeflate,!0,this.options.maxPayload);try{let d=To.parse(u);d[ze.extensionName]&&(c.accept(d[ze.extensionName]),h[ze.extensionName]=c)}catch{Ge(this,e,t,400,"Invalid or unacceptable Sec-WebSocket-Extensions header");return}}if(this.options.verifyClient){let c={origin:e.headers[`${a===8?"sec-websocket-origin":"origin"}`],secure:!!(e.socket.authorized||e.socket.encrypted),req:e};if(this.options.verifyClient.length===2){this.options.verifyClient(c,(d,m,p,_)=>{if(!d)return It(t,m||401,p,_);this.completeUpgrade(h,s,f,e,t,r,i)});return}if(!this.options.verifyClient(c))return It(t,401)}this.completeUpgrade(h,s,f,e,t,r,i)}completeUpgrade(e,t,r,i,s,o,a){if(!s.readable||!s.writable)return s.destroy();if(s[$u])throw new Error("server.handleUpgrade() was called more than once with the same socket, possibly due to a misconfiguration");if(this._state>Ro)return It(s,503);let f=["HTTP/1.1 101 Switching Protocols","Upgrade: websocket","Connection: Upgrade",`Sec-WebSocket-Accept: ${Gu("sha1").update(t+ju).digest("base64")}`],u=new this.options.WebSocket(null,void 0,this.options);if(r.size){let h=this.options.handleProtocols?this.options.handleProtocols(r,i):r.values().next().value;h&&(f.push(`Sec-WebSocket-Protocol: ${h}`),u._protocol=h)}if(e[ze.extensionName]){let h=e[ze.extensionName].params,c=To.format({[ze.extensionName]:[h]});f.push(`Sec-WebSocket-Extensions: ${c}`),u._extensions=e}this.emit("headers",f,i),s.write(f.concat(`\r +`).join(`\r +`)),s.removeListener("error",Do),u.setSocket(s,o,{allowSynchronousEvents:this.options.allowSynchronousEvents,maxPayload:this.options.maxPayload,skipUTF8Validation:this.options.skipUTF8Validation}),this.clients&&(this.clients.add(u),u.on("close",()=>{this.clients.delete(u),this._shouldEmitClose&&!this.clients.size&&process.nextTick(Ot,this)})),a(u,i)}};Po.exports=xn;function Hu(n,e){for(let t of Object.keys(e))n.on(t,e[t]);return function(){for(let r of Object.keys(e))n.removeListener(r,e[r])}}function Ot(n){n._state=Mo,n.emit("close")}function Do(){this.destroy()}function It(n,e,t,r){t=t||fr.STATUS_CODES[e],r={Connection:"close","Content-Type":"text/html","Content-Length":Buffer.byteLength(t),...r},n.once("finish",n.destroy),n.end(`HTTP/1.1 ${e} ${fr.STATUS_CODES[e]}\r +`+Object.keys(r).map(i=>`${i}: ${r[i]}`).join(`\r +`)+`\r +\r +`+t)}function Ge(n,e,t,r,i,s){if(n.listenerCount("wsClientError")){let o=new Error(i);Error.captureStackTrace(o,Ge),n.emit("wsClientError",o,t,e)}else It(t,r,i,s)}});var qo=b((gd,Wo)=>{"use strict";Wo.exports=zo;function zo(n,e,t){n instanceof RegExp&&(n=Bo(n,t)),e instanceof RegExp&&(e=Bo(e,t));var r=Go(n,e,t);return r&&{start:r[0],end:r[1],pre:t.slice(0,r[0]),body:t.slice(r[0]+n.length,r[1]),post:t.slice(r[1]+e.length)}}function Bo(n,e){var t=e.match(n);return t?t[0]:null}zo.range=Go;function Go(n,e,t){var r,i,s,o,a,l=t.indexOf(n),f=t.indexOf(e,l+1),u=l;if(l>=0&&f>0){if(n===e)return[l,f];for(r=[],s=t.length;u>=0&&!a;)u==l?(r.push(u),l=t.indexOf(n,u+1)):r.length==1?a=[r.pop(),f]:(i=r.pop(),i=0?l:f;r.length&&(a=[s,o])}return a}});var Ko=b((_d,Xo)=>{var jo=qo();Xo.exports=ec;var $o="\0SLASH"+Math.random()+"\0",Vo="\0OPEN"+Math.random()+"\0",bn="\0CLOSE"+Math.random()+"\0",Ho="\0COMMA"+Math.random()+"\0",Zo="\0PERIOD"+Math.random()+"\0";function Cn(n){return parseInt(n,10)==n?parseInt(n,10):n.charCodeAt(0)}function Ju(n){return n.split("\\\\").join($o).split("\\{").join(Vo).split("\\}").join(bn).split("\\,").join(Ho).split("\\.").join(Zo)}function Qu(n){return n.split($o).join("\\").split(Vo).join("{").split(bn).join("}").split(Ho).join(",").split(Zo).join(".")}function Yo(n){if(!n)return[""];var e=[],t=jo("{","}",n);if(!t)return n.split(",");var r=t.pre,i=t.body,s=t.post,o=r.split(",");o[o.length-1]+="{"+i+"}";var a=Yo(s);return s.length&&(o[o.length-1]+=a.shift(),o.push.apply(o,a)),e.push.apply(e,o),e}function ec(n){return n?(n.substr(0,2)==="{}"&&(n="\\{\\}"+n.substr(2)),Nt(Ju(n),!0).map(Qu)):[]}function tc(n){return"{"+n+"}"}function rc(n){return/^-?0\d/.test(n)}function nc(n,e){return n<=e}function ic(n,e){return n>=e}function Nt(n,e){var t=[],r=jo("{","}",n);if(!r)return[n];var i=r.pre,s=r.post.length?Nt(r.post,!1):[""];if(/\$$/.test(r.pre))for(var o=0;o=0;if(!u&&!h)return r.post.match(/,(?!,).*\}/)?(n=r.pre+"{"+r.body+bn+r.post,Nt(n)):[n];var c;if(u)c=r.body.split(/\.\./);else if(c=Yo(r.body),c.length===1&&(c=Nt(c[0],!1).map(tc),c.length===1))return s.map(function(G){return r.pre+c[0]+G});var d;if(u){var m=Cn(c[0]),p=Cn(c[1]),_=Math.max(c[0].length,c[1].length),v=c.length==3?Math.abs(Cn(c[2])):1,C=nc,I=p0){var P=new Array(B+1).join("0");R<0?O="-"+P+O.slice(1):O=P+O}}d.push(O)}}else{d=[];for(var A=0;A{"use strict";Object.defineProperty(Tn,"__esModule",{value:!0});Tn.default=jc;var At="diff-sequences",X=0,Dt=(n,e,t,r,i)=>{let s=0;for(;n{let s=0;for(;n<=e&&t<=r&&i(e,r);)e-=1,r-=1,s+=1;return s},In=(n,e,t,r,i,s,o)=>{let a=0,l=-n,f=s[a],u=f;s[a]+=Dt(f+1,e,r+f-l+1,t,i);let h=n{let a=0,l=n,f=s[a],u=f;s[a]-=Mt(e,f-1,t,r+f-l-1,i);let h=n{let h=r-e,c=t-e,m=i-r-c,p=-m-(n-1),_=-m+(n-1),v=X,C=n{let h=i-t,c=t-e,m=i-r-c,p=m-n,_=m+n,v=X,C=n{let f=r-e,u=i-t,h=t-e,c=i-r,d=c-h,m=h,p=h;if(o[0]=e-1,a[0]=t,d%2===0){let _=(n||d)/2,v=(h+c)/2;for(let C=1;C<=v;C+=1)if(m=In(C,t,i,f,s,o,m),C<_)p=ul(C,e,r,u,s,a,p);else if(Wc(C,e,t,r,i,s,o,m,a,p,l))return}else{let _=((n||d)+1)/2,v=(h+c+1)/2,C=1;for(m=In(C,t,i,f,s,o,m),C+=1;C<=v;C+=1)if(p=ul(C-1,e,r,u,s,a,p),C<_)m=In(C,t,i,f,s,o,m);else if(Gc(C,e,t,r,i,s,o,m,a,p,l))return}throw new Error(`${At}: no overlap aStart=${e} aEnd=${t} bStart=${r} bEnd=${i}`)},Nn=(n,e,t,r,i,s,o,a,l,f)=>{if(i-r{G(te,w,g)},isCommon:(te,g)=>fe(g,te)}}let P=e,A=t;e=r,t=i,r=P,i=A}let{foundSubsequence:u,isCommon:h}=o[s?1:0];qc(n,e,t,r,i,h,a,l,f);let{nChangePreceding:c,aEndPreceding:d,bEndPreceding:m,nCommonPreceding:p,aCommonPreceding:_,bCommonPreceding:v,nCommonFollowing:C,aCommonFollowing:I,bCommonFollowing:L,nChangeFollowing:R,aStartFollowing:O,bStartFollowing:B}=f;e{if(typeof e!="number")throw new TypeError(`${At}: ${n} typeof ${typeof e} is not a number`);if(!Number.isSafeInteger(e))throw new RangeError(`${At}: ${n} value ${e} is not a safe integer`);if(e<0)throw new RangeError(`${At}: ${n} value ${e} is a negative integer`)},hl=(n,e)=>{let t=typeof e;if(t!=="function")throw new TypeError(`${At}: ${n} typeof ${t} is not a function`)};function jc(n,e,t,r){cl("aLength",n),cl("bLength",e),hl("isCommon",t),hl("foundSubsequence",r);let i=Dt(0,n,0,e,t);if(i!==0&&r(i,0,0),n!==i||e!==i){let s=i,o=i,a=Mt(s,n-1,o,e-1,t),l=n-a,f=e-a,u=i+a;n!==u&&e!==u&&Nn(0,s,l,o,f,!1,[{foundSubsequence:r,isCommon:t}],[X],[X],{aCommonFollowing:X,aCommonPreceding:X,aEndPreceding:X,aStartFollowing:X,bCommonFollowing:X,bCommonPreceding:X,bEndPreceding:X,bStartFollowing:X,nChangeFollowing:X,nChangePreceding:X,nCommonFollowing:X,nCommonPreceding:X}),a!==0&&r(a,l,f)}}});var vl=b((Qd,Sl)=>{"use strict";function Xc(n){return n&&n.__esModule&&Object.prototype.hasOwnProperty.call(n,"default")?n.default:n}var Kc=new Int32Array([0,1996959894,3993919788,2567524794,124634137,1886057615,3915621685,2657392035,249268274,2044508324,3772115230,2547177864,162941995,2125561021,3887607047,2428444049,498536548,1789927666,4089016648,2227061214,450548861,1843258603,4107580753,2211677639,325883990,1684777152,4251122042,2321926636,335633487,1661365465,4195302755,2366115317,997073096,1281953886,3579855332,2724688242,1006888145,1258607687,3524101629,2768942443,901097722,1119000684,3686517206,2898065728,853044451,1172266101,3705015759,2882616665,651767980,1373503546,3369554304,3218104598,565507253,1454621731,3485111705,3099436303,671266974,1594198024,3322730930,2970347812,795835527,1483230225,3244367275,3060149565,1994146192,31158534,2563907772,4023717930,1907459465,112637215,2680153253,3904427059,2013776290,251722036,2517215374,3775830040,2137656763,141376813,2439277719,3865271297,1802195444,476864866,2238001368,4066508878,1812370925,453092731,2181625025,4111451223,1706088902,314042704,2344532202,4240017532,1658658271,366619977,2362670323,4224994405,1303535960,984961486,2747007092,3569037538,1256170817,1037604311,2765210733,3554079995,1131014506,879679996,2909243462,3663771856,1141124467,855842277,2852801631,3708648649,1342533948,654459306,3188396048,3373015174,1466479909,544179635,3110523913,3462522015,1591671054,702138776,2966460450,3352799412,1504918807,783551873,3082640443,3233442989,3988292384,2596254646,62317068,1957810842,3939845945,2647816111,81470997,1943803523,3814918930,2489596804,225274430,2053790376,3826175755,2466906013,167816743,2097651377,4027552580,2265490386,503444072,1762050814,4150417245,2154129355,426522225,1852507879,4275313526,2312317920,282753626,1742555852,4189708143,2394877945,397917763,1622183637,3604390888,2714866558,953729732,1340076626,3518719985,2797360999,1068828381,1219638859,3624741850,2936675148,906185462,1090812512,3747672003,2825379669,829329135,1181335161,3412177804,3160834842,628085408,1382605366,3423369109,3138078467,570562233,1426400815,3317316542,2998733608,733239954,1555261956,3268935591,3050360625,752459403,1541320221,2607071920,3965973030,1969922972,40735498,2617837225,3943577151,1913087877,83908371,2512341634,3803740692,2075208622,213261112,2463272603,3855990285,2094854071,198958881,2262029012,4057260610,1759359992,534414190,2176718541,4139329115,1873836001,414664567,2282248934,4279200368,1711684554,285281116,2405801727,4167216745,1634467795,376229701,2685067896,3608007406,1308918612,956543938,2808555105,3495958263,1231636301,1047427035,2932959818,3654703836,1088359270,936918e3,2847714899,3736837829,1202900863,817233897,3183342108,3401237130,1404277552,615818150,3134207493,3453421203,1423857449,601450431,3009837614,3294710456,1567103746,711928724,3020668471,3272380065,1510334235,755167117]);function yl(n){if(Buffer.isBuffer(n))return n;if(typeof n=="number")return Buffer.alloc(n);if(typeof n=="string")return Buffer.from(n);throw new Error("input must be buffer, number, or string, received "+typeof n)}function Jc(n){let e=yl(4);return e.writeInt32BE(n,0),e}function Dn(n,e){n=yl(n),Buffer.isBuffer(e)&&(e=e.readUInt32BE(0));let t=~~e^-1;for(var r=0;r>>8;return t^-1}function Mn(){return Jc(Dn.apply(null,arguments))}Mn.signed=function(){return Dn.apply(null,arguments)};Mn.unsigned=function(){return Dn.apply(null,arguments)>>>0};var Qc=Mn,eh=Xc(Qc);Sl.exports=eh});var zl=b(Gn=>{var xl=require("fs"),gr=require("stream").Transform,Ll=require("stream").PassThrough,Ol=require("zlib"),Bn=require("util"),th=require("events").EventEmitter,rh=require("events").errorMonitor,Il=vl();Gn.ZipFile=Te;Gn.dateToDosDateTime=Bl;Bn.inherits(Te,th);function Te(){this.outputStream=new Ll,this.entries=[],this.outputStreamCursor=0,this.ended=!1,this.allDone=!1,this.forceZip64Eocd=!1,this.errored=!1,this.on(rh,function(){this.errored=!0})}Te.prototype.addFile=function(n,e,t){var r=this;if(e=Er(e,!1),t==null&&(t={}),!_r(r)){var i=new D(e,!1,t);r.entries.push(i),xl.stat(n,function(s,o){if(s)return r.emit("error",s);if(!o.isFile())return r.emit("error",new Error("not a file: "+n));i.uncompressedSize=o.size,t.mtime==null&&i.setLastModDate(o.mtime),t.mode==null&&i.setFileAttributesMode(o.mode),i.setFileDataPumpFunction(function(){var a=xl.createReadStream(n);i.state=D.FILE_DATA_IN_PROGRESS,a.on("error",function(l){r.emit("error",l)}),Nl(r,i,a)}),Ne(r)})}};Te.prototype.addReadStream=function(n,e,t){this.addReadStreamLazy(e,t,function(r){r(null,n)})};Te.prototype.addReadStreamLazy=function(n,e,t){var r=this;if(typeof e=="function"&&(t=e,e=null),e==null&&(e={}),n=Er(n,!1),!_r(r)){var i=new D(n,!1,e);r.entries.push(i),i.setFileDataPumpFunction(function(){i.state=D.FILE_DATA_IN_PROGRESS,t(function(s,o){if(s)return r.emit("error",s);Nl(r,i,o)})}),Ne(r)}};Te.prototype.addBuffer=function(n,e,t){var r=this;if(e=Er(e,!1),n.length>1073741823)throw new Error("buffer too large: "+n.length+" > 1073741823");if(t==null&&(t={}),t.size!=null)throw new Error("options.size not allowed");if(_r(r))return;var i=new D(e,!1,t);i.uncompressedSize=n.length,i.crc32=Il.unsigned(n),i.crcAndFileSizeKnown=!0,r.entries.push(i),i.compressionLevel===0?s(n):Ol.deflateRaw(n,{level:i.compressionLevel},function(o,a){s(a)});function s(o){i.compressedSize=o.length,i.setFileDataPumpFunction(function(){We(r,o),We(r,i.getDataDescriptor()),i.state=D.FILE_DATA_DONE,setImmediate(function(){Ne(r)})}),Ne(r)}};Te.prototype.addEmptyDirectory=function(n,e){var t=this;if(n=Er(n,!0),e==null&&(e={}),e.size!=null)throw new Error("options.size not allowed");if(e.compress!=null)throw new Error("options.compress not allowed");if(e.compressionLevel!=null)throw new Error("options.compressionLevel not allowed");if(!_r(t)){var r=new D(n,!0,e);t.entries.push(r),r.setFileDataPumpFunction(function(){We(t,r.getDataDescriptor()),r.state=D.FILE_DATA_DONE,Ne(t)}),Ne(t)}};var nh=Ie([80,75,5,6]);Te.prototype.end=function(n,e){if(typeof n=="function"&&(e=n,n=null),n==null&&(n={}),!this.ended&&(this.ended=!0,!this.errored)){if(this.calculatedTotalSizeCallback=e,this.forceZip64Eocd=!!n.forceZip64Format,n.comment){if(typeof n.comment=="string"?this.comment=lh(n.comment):this.comment=n.comment,this.comment.length>65535)throw new Error("comment is too large");if(Pt(this.comment,nh))throw new Error("comment contains end of central directory record signature")}else this.comment=Ft;Ne(this)}};function We(n,e){n.outputStream.write(e),n.outputStreamCursor+=e.length}function Nl(n,e,t){var r=new zn,i=new mr,s=e.compressionLevel!==0?new Ol.DeflateRaw({level:e.compressionLevel}):new Ll,o=new mr;t.pipe(r).pipe(i).pipe(s).pipe(o).pipe(n.outputStream,{end:!1}),o.on("end",function(){if(e.crc32=r.crc32,e.uncompressedSize==null)e.uncompressedSize=i.byteCount;else if(e.uncompressedSize!==i.byteCount)return n.emit("error",new Error("file data stream has unexpected number of bytes"));e.compressedSize=o.byteCount,n.outputStreamCursor+=e.compressedSize,We(n,e.getDataDescriptor()),e.state=D.FILE_DATA_DONE,Ne(n)})}function ih(n){if(n.compress!=null&&n.compressionLevel!=null&&!!n.compress!=!!n.compressionLevel)throw new Error("conflicting settings for compress and compressionLevel");return n.compressionLevel!=null?n.compressionLevel:n.compress===!1?0:6}function Ne(n){if(n.allDone||n.errored)return;if(n.ended&&n.calculatedTotalSizeCallback!=null){var e=sh(n);e!=null&&(n.calculatedTotalSizeCallback(e),n.calculatedTotalSizeCallback=null)}var t=r();function r(){for(var s=0;s=D.READY_TO_PUMP_FILE_DATA){if(i.uncompressedSize==null)return-1}else if(i.uncompressedSize==null)return null;i.relativeOffsetOfLocalHeader=e;var s=i.useZip64Format();e+=Tl+i.utf8FileName.length,e+=i.uncompressedSize,i.crcAndFileSizeKnown||(s?e+=Ul:e+=Fl),t+=kl+i.utf8FileName.length+i.fileComment.length,i.forceDosTimestamp||(t+=Fn),s&&(t+=Un)}var o=0;return(n.forceZip64Eocd||n.entries.length>=65535||t>=65535||e>=4294967295)&&(o+=dr+Pn),o+=pr+n.comment.length,e+t+o}function _r(n){if(n.ended)throw new Error("cannot add entries after calling end()");return!!n.errored}var dr=56,Pn=20,pr=22;function oh(n,e){var t=!1,r=n.entries.length;(n.forceZip64Eocd||n.entries.length>=65535)&&(r=65535,t=!0);var i=n.outputStreamCursor-n.offsetOfStartOfCentralDirectory,s=i;(n.forceZip64Eocd||i>=4294967295)&&(s=4294967295,t=!0);var o=n.offsetOfStartOfCentralDirectory;if((n.forceZip64Eocd||n.offsetOfStartOfCentralDirectory>=4294967295)&&(o=4294967295,t=!0),e)return t?dr+Pn+pr:pr;var a=J(pr+n.comment.length);if(a.writeUInt32LE(101010256,0),a.writeUInt16LE(0,4),a.writeUInt16LE(0,6),a.writeUInt16LE(r,8),a.writeUInt16LE(r,10),a.writeUInt32LE(s,12),a.writeUInt32LE(o,16),a.writeUInt16LE(n.comment.length,20),n.comment.copy(a,22),!t)return a;var l=J(dr);l.writeUInt32LE(101075792,0),pe(l,dr-12,4),l.writeUInt16LE(Dl,12),l.writeUInt16LE(Al,14),l.writeUInt32LE(0,16),l.writeUInt32LE(0,20),pe(l,n.entries.length,24),pe(l,n.entries.length,32),pe(l,i,40),pe(l,n.offsetOfStartOfCentralDirectory,48);var f=J(Pn);return f.writeUInt32LE(117853008,0),f.writeUInt32LE(0,4),pe(f,n.outputStreamCursor,8),f.writeUInt32LE(1,16),Buffer.concat([l,f,a])}function Er(n,e){if(n==="")throw new Error("empty metadataPath");if(n=n.replace(/\\/g,"/"),/^[a-zA-Z]:/.test(n)||/^\//.test(n))throw new Error("absolute path: "+n);if(n.split("/").indexOf("..")!==-1)throw new Error("invalid relative path: "+n);var t=/\/$/.test(n);if(e)t||(n+="/");else if(t)throw new Error("file path cannot end with '/': "+n);return n}var Ft=J(0);function D(n,e,t){if(this.utf8FileName=Ie(n),this.utf8FileName.length>65535)throw new Error("utf8 file name too long. "+utf8FileName.length+" > 65535");if(this.isDirectory=e,this.state=D.WAITING_FOR_METADATA,this.setLastModDate(t.mtime!=null?t.mtime:new Date),this.forceDosTimestamp=!!t.forceDosTimestamp,t.mode!=null?this.setFileAttributesMode(t.mode):this.setFileAttributesMode(e?16893:33204),e?(this.crcAndFileSizeKnown=!0,this.crc32=0,this.uncompressedSize=0,this.compressedSize=0):(this.crcAndFileSizeKnown=!1,this.crc32=null,this.uncompressedSize=null,this.compressedSize=null,t.size!=null&&(this.uncompressedSize=t.size)),e?this.compressionLevel=0:this.compressionLevel=ih(t),this.forceZip64Format=!!t.forceZip64Format,t.fileComment){if(typeof t.fileComment=="string"?this.fileComment=Ie(t.fileComment,"utf-8"):this.fileComment=t.fileComment,this.fileComment.length>65535)throw new Error("fileComment is too large")}else this.fileComment=Ft}D.WAITING_FOR_METADATA=0;D.READY_TO_PUMP_FILE_DATA=1;D.FILE_DATA_IN_PROGRESS=2;D.FILE_DATA_DONE=3;D.prototype.setLastModDate=function(n){this.mtime=n;var e=Bl(n);this.lastModFileTime=e.time,this.lastModFileDate=e.date};D.prototype.setFileAttributesMode=function(n){if((n&65535)!==n)throw new Error("invalid mode. expected: 0 <= "+n+" <= 65535");this.externalFileAttributes=n<<16>>>0};D.prototype.setFileDataPumpFunction=function(n){this.doFileDataPump=n,this.state=D.READY_TO_PUMP_FILE_DATA};D.prototype.useZip64Format=function(){return this.forceZip64Format||this.uncompressedSize!=null&&this.uncompressedSize>4294967294||this.compressedSize!=null&&this.compressedSize>4294967294||this.relativeOffsetOfLocalHeader!=null&&this.relativeOffsetOfLocalHeader>4294967294};var Tl=30,Rl=20,Al=45,Dl=831,Ml=2048,Pl=8;D.prototype.getLocalFileHeader=function(){var n=0,e=0,t=0;this.crcAndFileSizeKnown&&(n=this.crc32,e=this.compressedSize,t=this.uncompressedSize);var r=J(Tl),i=Ml;return this.crcAndFileSizeKnown||(i|=Pl),r.writeUInt32LE(67324752,0),r.writeUInt16LE(Rl,4),r.writeUInt16LE(i,6),r.writeUInt16LE(this.getCompressionMethod(),8),r.writeUInt16LE(this.lastModFileTime,10),r.writeUInt16LE(this.lastModFileDate,12),r.writeUInt32LE(n,14),r.writeUInt32LE(e,18),r.writeUInt32LE(t,22),r.writeUInt16LE(this.utf8FileName.length,26),r.writeUInt16LE(0,28),Buffer.concat([r,this.utf8FileName])};var Fl=16,Ul=24;D.prototype.getDataDescriptor=function(){if(this.crcAndFileSizeKnown)return Ft;if(this.useZip64Format()){var n=J(Ul);return n.writeUInt32LE(134695760,0),n.writeUInt32LE(this.crc32,4),pe(n,this.compressedSize,8),pe(n,this.uncompressedSize,16),n}else{var n=J(Fl);return n.writeUInt32LE(134695760,0),n.writeUInt32LE(this.crc32,4),n.writeUInt32LE(this.compressedSize,8),n.writeUInt32LE(this.uncompressedSize,12),n}};var kl=46,Fn=9,Un=28;D.prototype.getCentralDirectoryRecord=function(){var n=J(kl),e=Ml;this.crcAndFileSizeKnown||(e|=Pl);var t=Ft;if(!this.forceDosTimestamp){t=J(Fn),t.writeUInt16LE(21589,0),t.writeUInt16LE(Fn-4,2);var r=1,i=2;t.writeUInt8(r|i,4);var s=Math.floor(this.mtime.getTime()/1e3);s<-2147483648&&(s=-2147483648),s>2147483647&&(s=2147483647),t.writeUInt32LE(s,5)}var o=this.compressedSize,a=this.uncompressedSize,l=this.relativeOffsetOfLocalHeader,f=Rl,u=Ft;return this.useZip64Format()&&(o=4294967295,a=4294967295,l=4294967295,f=Al,u=J(Un),u.writeUInt16LE(1,0),u.writeUInt16LE(Un-4,2),pe(u,this.uncompressedSize,4),pe(u,this.compressedSize,12),pe(u,this.relativeOffsetOfLocalHeader,20)),n.writeUInt32LE(33639248,0),n.writeUInt16LE(Dl,4),n.writeUInt16LE(f,6),n.writeUInt16LE(e,8),n.writeUInt16LE(this.getCompressionMethod(),10),n.writeUInt16LE(this.lastModFileTime,12),n.writeUInt16LE(this.lastModFileDate,14),n.writeUInt32LE(this.crc32,16),n.writeUInt32LE(o,20),n.writeUInt32LE(a,24),n.writeUInt16LE(this.utf8FileName.length,28),n.writeUInt16LE(t.length+u.length,30),n.writeUInt16LE(this.fileComment.length,32),n.writeUInt16LE(0,34),n.writeUInt16LE(0,36),n.writeUInt32LE(this.externalFileAttributes,38),n.writeUInt32LE(l,42),Buffer.concat([n,this.utf8FileName,t,u,this.fileComment])};D.prototype.getCompressionMethod=function(){var n=0,e=8;return this.compressionLevel===0?n:e};var Cl=new Date(1980,0,1),bl=new Date(2107,11,31,23,59,58);function Bl(n){nbl&&(n=bl);var e=0;e|=n.getDate()&31,e|=(n.getMonth()+1&15)<<5,e|=(n.getFullYear()-1980&127)<<9;var t=0;return t|=Math.floor(n.getSeconds()/2),t|=(n.getMinutes()&63)<<5,t|=(n.getHours()&31)<<11,{date:e,time:t}}function pe(n,e,t){var r=Math.floor(e/4294967296),i=e%4294967296;n.writeUInt32LE(i,t),n.writeUInt32LE(r,t+4)}Bn.inherits(mr,gr);function mr(n){gr.call(this,n),this.byteCount=0}mr.prototype._transform=function(n,e,t){this.byteCount+=n.length,t(null,n)};Bn.inherits(zn,gr);function zn(n){gr.call(this,n),this.crc32=0}zn.prototype._transform=function(n,e,t){this.crc32=Il.unsigned(n,this.crc32),t(null,n)};var kn="\0\u263A\u263B\u2665\u2666\u2663\u2660\u2022\u25D8\u25CB\u25D9\u2642\u2640\u266A\u266B\u263C\u25BA\u25C4\u2195\u203C\xB6\xA7\u25AC\u21A8\u2191\u2193\u2192\u2190\u221F\u2194\u25B2\u25BC !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\u2302\xC7\xFC\xE9\xE2\xE4\xE0\xE5\xE7\xEA\xEB\xE8\xEF\xEE\xEC\xC4\xC5\xC9\xE6\xC6\xF4\xF6\xF2\xFB\xF9\xFF\xD6\xDC\xA2\xA3\xA5\u20A7\u0192\xE1\xED\xF3\xFA\xF1\xD1\xAA\xBA\xBF\u2310\xAC\xBD\xBC\xA1\xAB\xBB\u2591\u2592\u2593\u2502\u2524\u2561\u2562\u2556\u2555\u2563\u2551\u2557\u255D\u255C\u255B\u2510\u2514\u2534\u252C\u251C\u2500\u253C\u255E\u255F\u255A\u2554\u2569\u2566\u2560\u2550\u256C\u2567\u2568\u2564\u2565\u2559\u2558\u2552\u2553\u256B\u256A\u2518\u250C\u2588\u2584\u258C\u2590\u2580\u03B1\xDF\u0393\u03C0\u03A3\u03C3\xB5\u03C4\u03A6\u0398\u03A9\u03B4\u221E\u03C6\u03B5\u2229\u2261\xB1\u2265\u2264\u2320\u2321\xF7\u2248\xB0\u2219\xB7\u221A\u207F\xB2\u25A0\xA0";if(kn.length!==256)throw new Error("assertion failure");var hr=null;function lh(n){if(/^[\x20-\x7e]*$/.test(n))return Ie(n,"utf-8");if(hr==null){hr={};for(var e=0;e{var le=require("fs"),ah=require("util"),ot=require("path"),Zn=require("events"),Gl=require("zlib"),jl=require("stream"),E={LOCHDR:30,LOCSIG:67324752,LOCVER:4,LOCFLG:6,LOCHOW:8,LOCTIM:10,LOCCRC:14,LOCSIZ:18,LOCLEN:22,LOCNAM:26,LOCEXT:28,EXTSIG:134695760,EXTHDR:16,EXTCRC:4,EXTSIZ:8,EXTLEN:12,CENHDR:46,CENSIG:33639248,CENVEM:4,CENVER:6,CENFLG:8,CENHOW:10,CENTIM:12,CENCRC:16,CENSIZ:20,CENLEN:24,CENNAM:28,CENEXT:30,CENCOM:32,CENDSK:34,CENATT:36,CENATX:38,CENOFF:42,ENDHDR:22,ENDSIG:101010256,ENDSIGFIRST:80,ENDSUB:8,ENDTOT:10,ENDSIZ:12,ENDOFF:16,ENDCOM:20,MAXFILECOMMENT:65535,ENDL64HDR:20,ENDL64SIG:117853008,ENDL64SIGFIRST:80,ENDL64OFS:8,END64HDR:56,END64SIG:101075792,END64SIGFIRST:80,END64SUB:24,END64TOT:32,END64SIZ:40,END64OFF:48,STORED:0,SHRUNK:1,REDUCED1:2,REDUCED2:3,REDUCED3:4,REDUCED4:5,IMPLODED:6,DEFLATED:8,ENHANCED_DEFLATED:9,PKWARE:10,BZIP2:12,LZMA:14,IBM_TERSE:18,IBM_LZ77:19,FLG_ENC:0,FLG_COMP1:1,FLG_COMP2:2,FLG_DESC:4,FLG_ENH:8,FLG_STR:16,FLG_LNG:1024,FLG_MSK:4096,FLG_ENTRY_ENC:1,EF_ID:0,EF_SIZE:2,ID_ZIP64:1,ID_AVINFO:7,ID_PFS:8,ID_OS2:9,ID_NTFS:10,ID_OPENVMS:12,ID_UNIX:13,ID_FORK:14,ID_PATCH:15,ID_X509_PKCS7:20,ID_X509_CERTID_F:21,ID_X509_CERTID_C:22,ID_STRONGENC:23,ID_RECORD_MGT:24,ID_X509_PKCS7_RL:25,ID_IBM1:101,ID_IBM2:102,ID_POSZIP:18064,EF_ZIP64_OR_32:4294967295,EF_ZIP64_OR_16:65535},Me=function(n){let e,t,r,i,s,o,l=this,f=n.storeEntries!==!1?{}:null,u=n.file,h=n.nameEncoding?new TextDecoder(n.nameEncoding):null;c();function c(){n.fd?(e=n.fd,d()):le.open(u,"r",(g,w)=>{if(g)return l.emit("error",g);e=w,d()})}function d(){le.fstat(e,(g,w)=>{if(g)return l.emit("error",g);t=w.size,r=n.chunkSize||Math.round(t/1e3),r=Math.max(Math.min(r,Math.min(128*1024,t)),Math.min(1024,t)),p()})}function m(g,w){if(g||!w)return l.emit("error",g||new Error("Archive read error"));let x=i.lastPos,y=x-i.win.position,T=i.win.buffer,N=i.minPos;for(;--x>=N&&--y>=0;)if(T.length-y>=4&&T[y]===i.firstByte&&T.readUInt32LE(y)===i.sig){i.lastBufferPosition=y,i.lastBytesRead=w,i.complete();return}if(x===N)return l.emit("error",new Error("Bad archive"));if(i.lastPos=x+1,i.chunkSize*=2,x<=N)return l.emit("error",new Error("Bad archive"));let F=Math.min(i.chunkSize,x-N);i.win.expandLeft(F,m)}function p(){let g=Math.min(E.ENDHDR+E.MAXFILECOMMENT,t);i={win:new wr(e),totalReadLength:g,minPos:t-g,lastPos:t,chunkSize:Math.min(1024,r),firstByte:E.ENDSIGFIRST,sig:E.ENDSIG,complete:_},i.win.read(t-i.chunkSize,i.chunkSize,m)}function _(){let g=i.win.buffer,w=i.lastBufferPosition;try{s=new Wn,s.read(g.slice(w,w+E.ENDHDR)),s.headerOffset=i.win.position+w,s.commentLength?l.comment=g.slice(w+E.ENDHDR,w+E.ENDHDR+s.commentLength).toString():l.comment=null,l.entriesCount=s.volumeEntries,l.centralDirectory=s,s.volumeEntries===E.EF_ZIP64_OR_16&&s.totalEntries===E.EF_ZIP64_OR_16||s.size===E.EF_ZIP64_OR_32||s.offset===E.EF_ZIP64_OR_32?v():(i={},L())}catch(x){l.emit("error",x)}}function v(){let g=E.ENDL64HDR;i.lastBufferPosition>g?(i.lastBufferPosition-=g,C()):(i={win:i.win,totalReadLength:g,minPos:i.win.position-g,lastPos:i.win.position,chunkSize:i.chunkSize,firstByte:E.ENDL64SIGFIRST,sig:E.ENDL64SIG,complete:C},i.win.read(i.lastPos-i.chunkSize,i.chunkSize,m))}function C(){let g=i.win.buffer,w=new qn;w.read(g.slice(i.lastBufferPosition,i.lastBufferPosition+E.ENDL64HDR));let x=t-w.headerOffset;i={win:i.win,totalReadLength:x,minPos:w.headerOffset,lastPos:i.lastPos,chunkSize:i.chunkSize,firstByte:E.END64SIGFIRST,sig:E.END64SIG,complete:I},i.win.read(t-i.chunkSize,i.chunkSize,m)}function I(){let g=i.win.buffer,w=new jn;w.read(g.slice(i.lastBufferPosition,i.lastBufferPosition+E.END64HDR)),l.centralDirectory.volumeEntries=w.volumeEntries,l.centralDirectory.totalEntries=w.totalEntries,l.centralDirectory.size=w.size,l.centralDirectory.offset=w.offset,l.entriesCount=w.volumeEntries,i={},L()}function L(){i={win:new wr(e),pos:s.offset,chunkSize:r,entriesLeft:s.volumeEntries},i.win.read(i.pos,Math.min(r,t-i.pos),R)}function R(g,w){if(g||!w)return l.emit("error",g||new Error("Entries read error"));let x=i.pos-i.win.position,y=i.entry,T=i.win.buffer,N=T.length;try{for(;i.entriesLeft>0;){y||(y=new $n,y.readHeader(T,x),y.headerOffset=i.win.position+x,i.entry=y,i.pos+=E.CENHDR,x+=E.CENHDR);let F=y.fnameLen+y.extraLen+y.comLen,q=F+(i.entriesLeft>1?E.CENHDR:0);if(N-x{if(x)return w(x);let T=B(y),N=new Vn(e,T,y.compressedSize);if(y.method!==E.STORED)if(y.method===E.DEFLATED)N=N.pipe(Gl.createInflateRaw());else return w(new Error("Unknown compression method: "+y.method));P(y)&&(N=N.pipe(new Hn(N,y.crc,y.size))),w(null,N)},!1)},this.entryDataSync=function(g){let w=null;if(this.openEntry(g,(y,T)=>{w=y,g=T},!0),w)throw w;let x=Buffer.alloc(g.compressedSize);if(new Ae(e,x,0,g.compressedSize,B(g),y=>{w=y}).read(!0),w)throw w;if(g.method!==E.STORED)if(g.method===E.DEFLATED||g.method===E.ENHANCED_DEFLATED)x=Gl.inflateRawSync(x);else throw new Error("Unknown compression method: "+g.method);if(x.length!==g.size)throw new Error("Invalid size");return P(g)&&new yr(g.crc,g.size).data(x),x},this.openEntry=function(g,w,x){if(typeof g=="string"&&(O(),g=f[g],!g))return w(new Error("Entry not found"));if(!g.isFile)return w(new Error("Entry is not file"));if(!e)return w(new Error("Archive closed"));let y=Buffer.alloc(E.LOCHDR);new Ae(e,y,0,y.length,g.offset,T=>{if(T)return w(T);let N;try{g.readDataHeader(y),g.encrypted&&(N=new Error("Entry encrypted"))}catch(F){N=F}w(N,g)}).read(x)};function B(g){return g.offset+E.LOCHDR+g.fnameLen+g.extraLen}function P(g){return(g.flags&8)!==8}function A(g,w,x){l.stream(g,(y,T)=>{if(y)x(y);else{let N,F;T.on("error",q=>{F=q,N&&(T.unpipe(N),N.close(()=>{x(q)}))}),le.open(w,"w",(q,ue)=>{if(q)return x(q);if(F){le.close(e,()=>{x(F)});return}N=le.createWriteStream(w,{fd:ue}),N.on("finish",()=>{l.emit("extract",g,w),F||x()}),T.pipe(N)})}})}function G(g,w,x){if(!w.length)return x();let y=w.shift();y=ot.join(g,ot.join(...y)),le.mkdir(y,{recursive:!0},T=>{if(T&&T.code!=="EEXIST")return x(T);G(g,w,x)})}function fe(g,w,x,y,T){if(!x.length)return y(null,T);let N=x.shift(),F=ot.join(g,N.name.replace(w,""));A(N,F,q=>{if(q)return y(q,T);fe(g,w,x,y,T+1)})}this.extract=function(g,w,x){let y=g||"";if(typeof g=="string"&&(g=this.entry(g),g?y=g.name:y.length&&y[y.length-1]!=="/"&&(y+="/")),!g||g.isDirectory){let T=[],N=[],F={};for(let q in f)if(Object.prototype.hasOwnProperty.call(f,q)&&q.lastIndexOf(y,0)===0){let ue=q.replace(y,""),Xn=f[q];if(Xn.isFile&&(T.push(Xn),ue=ot.dirname(ue)),ue&&!F[ue]&&ue!=="."){F[ue]=!0;let xe=ue.split("/").filter(lt=>lt);for(xe.length&&N.push(xe);xe.length>1;){xe=xe.slice(0,xe.length-1);let lt=xe.join("/");if(F[lt]||lt===".")break;F[lt]=!0,N.push(xe)}}}N.sort((q,ue)=>q.length-ue.length),N.length?G(w,N,q=>{q?x(q):fe(w,y,T,x,0)}):fe(w,y,T,x,0)}else le.stat(w,(T,N)=>{N&&N.isDirectory()?A(g,ot.join(w,ot.basename(g.name)),x):A(g,w,x)})},this.close=function(g){o||!e?(o=!0,g&&g()):(o=!0,le.close(e,w=>{e=null,g&&g(w)}))};let te=Zn.EventEmitter.prototype.emit;this.emit=function(...g){if(!o)return te.call(this,...g)}};Me.setFs=function(n){le=n};Me.debugLog=(...n)=>{Me.debug&&console.log(...n)};ah.inherits(Me,Zn.EventEmitter);var Re=Symbol("zip");Me.async=class extends Zn.EventEmitter{constructor(e){super();let t=new Me(e);t.on("entry",r=>this.emit("entry",r)),t.on("extract",(r,i)=>this.emit("extract",r,i)),this[Re]=new Promise((r,i)=>{t.on("ready",()=>{t.removeListener("error",i),r(t)}),t.on("error",i)})}get entriesCount(){return this[Re].then(e=>e.entriesCount)}get comment(){return this[Re].then(e=>e.comment)}async entry(e){return(await this[Re]).entry(e)}async entries(){return(await this[Re]).entries()}async stream(e){let t=await this[Re];return new Promise((r,i)=>{t.stream(e,(s,o)=>{s?i(s):r(o)})})}async entryData(e){let t=await this.stream(e);return new Promise((r,i)=>{let s=[];t.on("data",o=>s.push(o)),t.on("end",()=>{r(Buffer.concat(s))}),t.on("error",o=>{t.removeAllListeners("end"),i(o)})})}async extract(e,t){let r=await this[Re];return new Promise((i,s)=>{r.extract(e,t,(o,a)=>{o?s(o):i(a)})})}async close(){let e=await this[Re];return new Promise((t,r)=>{e.close(i=>{i?r(i):t()})})}};var Wn=class{read(e){if(e.length!==E.ENDHDR||e.readUInt32LE(0)!==E.ENDSIG)throw new Error("Invalid central directory");this.volumeEntries=e.readUInt16LE(E.ENDSUB),this.totalEntries=e.readUInt16LE(E.ENDTOT),this.size=e.readUInt32LE(E.ENDSIZ),this.offset=e.readUInt32LE(E.ENDOFF),this.commentLength=e.readUInt16LE(E.ENDCOM)}},qn=class{read(e){if(e.length!==E.ENDL64HDR||e.readUInt32LE(0)!==E.ENDL64SIG)throw new Error("Invalid zip64 central directory locator");this.headerOffset=De(e,E.ENDSUB)}},jn=class{read(e){if(e.length!==E.END64HDR||e.readUInt32LE(0)!==E.END64SIG)throw new Error("Invalid central directory");this.volumeEntries=De(e,E.END64SUB),this.totalEntries=De(e,E.END64TOT),this.size=De(e,E.END64SIZ),this.offset=De(e,E.END64OFF)}},$n=class{readHeader(e,t){if(e.length=8&&this.size===E.EF_ZIP64_OR_32&&(this.size=De(e,t),t+=8,r-=8),r>=8&&this.compressedSize===E.EF_ZIP64_OR_32&&(this.compressedSize=De(e,t),t+=8,r-=8),r>=8&&this.offset===E.EF_ZIP64_OR_32&&(this.offset=De(e,t),t+=8,r-=8),r>=4&&this.diskStart===E.EF_ZIP64_OR_16&&(this.diskStart=e.readUInt32LE(t))}get encrypted(){return(this.flags&E.FLG_ENTRY_ENC)===E.FLG_ENTRY_ENC}get isFile(){return!this.isDirectory}},Ae=class{constructor(e,t,r,i,s,o){this.fd=e,this.buffer=t,this.offset=r,this.length=i,this.position=s,this.callback=o,this.bytesRead=0,this.waiting=!1}read(e){Me.debugLog("read",this.position,this.bytesRead,this.length,this.offset),this.waiting=!0;let t;if(e){let r=0;try{r=le.readSync(this.fd,this.buffer,this.offset+this.bytesRead,this.length-this.bytesRead,this.position+this.bytesRead)}catch(i){t=i}this.readCallback(e,t,t?r:null)}else le.read(this.fd,this.buffer,this.offset+this.bytesRead,this.length-this.bytesRead,this.position+this.bytesRead,this.readCallback.bind(this,e))}readCallback(e,t,r){if(typeof r=="number"&&(this.bytesRead+=r),t||!r||this.bytesRead===this.length)return this.waiting=!1,this.callback(t,this.bytesRead);this.read(e)}},wr=class{constructor(e){this.position=0,this.buffer=Buffer.alloc(0),this.fd=e,this.fsOp=null}checkOp(){if(this.fsOp&&this.fsOp.waiting)throw new Error("Operation in progress")}read(e,t,r){this.checkOp(),this.buffer.length{this.emit("error",i)})}_transform(e,t,r){let i;try{this.verify.data(e)}catch(s){i=s}r(i,e)}},yr=class n{constructor(e,t){this.crc=e,this.size=t,this.state={crc:-1,size:0}}data(e){let t=n.getCrcTable(),r=this.state.crc,i=0,s=e.length;for(;--s>=0;)r=t[(r^e[i++])&255]^r>>>8;if(this.state.crc=r,this.state.size+=e.length,this.state.size>=this.size){let o=Buffer.alloc(4);if(o.writeInt32LE(~this.state.crc&4294967295,0),r=o.readUInt32LE(0),r!==this.crc)throw new Error("Invalid CRC");if(this.state.size!==this.size)throw new Error("Invalid size")}}static getCrcTable(){let e=n.crcTable;if(!e){n.crcTable=e=[];let t=Buffer.alloc(4);for(let r=0;r<256;r++){let i=r;for(let s=8;--s>=0;)(i&1)!==0?i=3988292384^i>>>1:i=i>>>1;i<0&&(t.writeInt32LE(i,0),i=t.readUInt32LE(0)),e[r]=i}}return e}};function Wl(n,e){let t=ql(n,16),r=ql(e,16),i={h:parseInt(t.slice(0,5).join(""),2),m:parseInt(t.slice(5,11).join(""),2),s:parseInt(t.slice(11,16).join(""),2)*2,Y:parseInt(r.slice(0,7).join(""),2)+1980,M:parseInt(r.slice(7,11).join(""),2),D:parseInt(r.slice(11,16).join(""),2)},s=[i.Y,i.M,i.D].join("-")+" "+[i.h,i.m,i.s].join(":")+" GMT+0";return new Date(s).getTime()}function ql(n,e){let t=(n>>>0).toString(2);for(;t.lengthQl.async,WebSocket:()=>ko,ZipFile:()=>Jl.ZipFile,convertSourceMap:()=>dh,decode:()=>ni,diffSequence:()=>Kl.default,findUpSync:()=>wl,minimatch:()=>Z,parseCss:()=>Xl.default,supportsColor:()=>Yl});module.exports=oa(ph);var dh=j(Qn());var ma=44;var ei="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",ga=new Uint8Array(64),ri=new Uint8Array(128);for(let n=0;n>>=1,s&&(t=-2147483648|-t),e+t}function ti(n,e){return n.pos>=e?!1:n.peek()!==ma}var _h=1024*16;var _a=class{constructor(n){this.pos=0,this.buffer=n}next(){return this.buffer.charCodeAt(this.pos++)}peek(){return this.buffer.charCodeAt(this.pos)}indexOf(n){let{buffer:e,pos:t}=this,r=e.indexOf(n,t);return r===-1?e.length:r}};function ni(n){let{length:e}=n,t=new _a(n),r=[],i=0,s=0,o=0,a=0,l=0;do{let f=t.indexOf(";"),u=[],h=!0,c=0;for(i=0;t.pos{if(typeof n!="string")throw new TypeError("invalid pattern");if(n.length>65536)throw new TypeError("pattern is too long")};var sc={"[:alnum:]":["\\p{L}\\p{Nl}\\p{Nd}",!0],"[:alpha:]":["\\p{L}\\p{Nl}",!0],"[:ascii:]":["\\x00-\\x7f",!1],"[:blank:]":["\\p{Zs}\\t",!0],"[:cntrl:]":["\\p{Cc}",!0],"[:digit:]":["\\p{Nd}",!0],"[:graph:]":["\\p{Z}\\p{C}",!0,!0],"[:lower:]":["\\p{Ll}",!0],"[:print:]":["\\p{C}",!0],"[:punct:]":["\\p{P}",!0],"[:space:]":["\\p{Z}\\t\\r\\n\\v\\f",!0],"[:upper:]":["\\p{Lu}",!0],"[:word:]":["\\p{L}\\p{Nl}\\p{Nd}\\p{Pc}",!0],"[:xdigit:]":["A-Fa-f0-9",!1]},Rt=n=>n.replace(/[[\]\\-]/g,"\\$&"),oc=n=>n.replace(/[-[\]{}()*+?.,\\^$|#\s]/g,"\\$&"),Jo=n=>n.join(""),Qo=(n,e)=>{let t=e;if(n.charAt(t)!=="[")throw new Error("not in a brace expression");let r=[],i=[],s=t+1,o=!1,a=!1,l=!1,f=!1,u=t,h="";e:for(;sh?r.push(Rt(h)+"-"+Rt(p)):p===h&&r.push(Rt(p)),h="",s++;continue}if(n.startsWith("-]",s+1)){r.push(Rt(p+"-")),s+=2;continue}if(n.startsWith("-",s+1)){h=p,s+=2;continue}r.push(Rt(p)),s++}if(ue?n.replace(/\[([^\/\\])\]/g,"$1"):n.replace(/((?!\\).|^)\[([^\/\\])\]/g,"$1$2").replace(/\\([^\/])/g,"$1");var lc=new Set(["!","?","+","*","@"]),el=n=>lc.has(n),ac="(?!(?:^|/)\\.\\.?(?:$|/))",ur="(?!\\.)",fc=new Set(["[","."]),uc=new Set(["..","."]),cc=new Set("().*{}+?[]^$\\!"),hc=n=>n.replace(/[-[\]{}()*+?.,\\^$|#\s]/g,"\\$&"),Ln="[^/]",tl=Ln+"*?",rl=Ln+"+?",nt=class n{type;#r;#n;#s=!1;#e=[];#t;#o;#a;#l=!1;#i;#f;#c=!1;constructor(e,t,r={}){this.type=e,e&&(this.#n=!0),this.#t=t,this.#r=this.#t?this.#t.#r:this,this.#i=this.#r===this?r:this.#r.#i,this.#a=this.#r===this?[]:this.#r.#a,e==="!"&&!this.#r.#l&&this.#a.push(this),this.#o=this.#t?this.#t.#e.length:0}get hasMagic(){if(this.#n!==void 0)return this.#n;for(let e of this.#e)if(typeof e!="string"&&(e.type||e.hasMagic))return this.#n=!0;return this.#n}toString(){return this.#f!==void 0?this.#f:this.type?this.#f=this.type+"("+this.#e.map(e=>String(e)).join("|")+")":this.#f=this.#e.map(e=>String(e)).join("")}#d(){if(this!==this.#r)throw new Error("should only call on root");if(this.#l)return this;this.toString(),this.#l=!0;let e;for(;e=this.#a.pop();){if(e.type!=="!")continue;let t=e,r=t.#t;for(;r;){for(let i=t.#o+1;!r.type&&itypeof r=="string"?r:r.toJSON()):[this.type,...this.#e.map(r=>r.toJSON())];return this.isStart()&&!this.type&&e.unshift([]),this.isEnd()&&(this===this.#r||this.#r.#l&&((t=this.#t)==null?void 0:t.type)==="!")&&e.push({}),e}isStart(){var t;if(this.#r===this)return!0;if(!((t=this.#t)!=null&&t.isStart()))return!1;if(this.#o===0)return!0;let e=this.#t;for(let r=0;r{let[p,_,v,C]=typeof m=="string"?n.#p(m,this.#n,f):m.toRegExpSource(e);return this.#n=this.#n||v,this.#s=this.#s||C,p}).join(""),h="";if(this.isStart()&&typeof this.#e[0]=="string"&&!(this.#e.length===1&&uc.has(this.#e[0]))){let p=fc,_=t&&p.has(u.charAt(0))||u.startsWith("\\.")&&p.has(u.charAt(2))||u.startsWith("\\.\\.")&&p.has(u.charAt(4)),v=!t&&!e&&p.has(u.charAt(0));h=_?ac:v?ur:""}let c="";return this.isEnd()&&this.#r.#l&&((l=this.#t)==null?void 0:l.type)==="!"&&(c="(?:$|\\/)"),[h+u+c,Oe(u),this.#n=!!this.#n,this.#s]}let r=this.type==="*"||this.type==="+",i=this.type==="!"?"(?:(?!(?:":"(?:",s=this.#h(t);if(this.isStart()&&this.isEnd()&&!s&&this.type!=="!"){let f=this.toString();return this.#e=[f],this.type=null,this.#n=void 0,[f,Oe(this.toString()),!1,!1]}let o=!r||e||t||!ur?"":this.#h(!0);o===s&&(o=""),o&&(s=`(?:${s})(?:${o})*?`);let a="";if(this.type==="!"&&this.#c)a=(this.isStart()&&!t?ur:"")+rl;else{let f=this.type==="!"?"))"+(this.isStart()&&!t&&!e?ur:"")+tl+")":this.type==="@"?")":this.type==="?"?")?":this.type==="+"&&o?")":this.type==="*"&&o?")?":`)${this.type}`;a=i+s+f}return[a,Oe(s),this.#n=!!this.#n,this.#s]}#h(e){return this.#e.map(t=>{if(typeof t=="string")throw new Error("string type in extglob ast??");let[r,i,s,o]=t.toRegExpSource(e);return this.#s=this.#s||o,r}).filter(t=>!(this.isStart()&&this.isEnd())||!!t).join("|")}static#p(e,t,r=!1){let i=!1,s="",o=!1;for(let a=0;ae?n.replace(/[?*()[\]]/g,"[$&]"):n.replace(/[?*()[\]\\]/g,"\\$&");var Z=(n,e,t={})=>(Tt(e),!t.nocomment&&e.charAt(0)==="#"?!1:new it(e,t).match(n)),dc=/^\*+([^+@!?\*\[\(]*)$/,pc=n=>e=>!e.startsWith(".")&&e.endsWith(n),mc=n=>e=>e.endsWith(n),gc=n=>(n=n.toLowerCase(),e=>!e.startsWith(".")&&e.toLowerCase().endsWith(n)),_c=n=>(n=n.toLowerCase(),e=>e.toLowerCase().endsWith(n)),Ec=/^\*+\.\*+$/,wc=n=>!n.startsWith(".")&&n.includes("."),yc=n=>n!=="."&&n!==".."&&n.includes("."),Sc=/^\.\*+$/,vc=n=>n!=="."&&n!==".."&&n.startsWith("."),xc=/^\*+$/,Cc=n=>n.length!==0&&!n.startsWith("."),bc=n=>n.length!==0&&n!=="."&&n!=="..",Lc=/^\?+([^+@!?\*\[\(]*)?$/,Oc=([n,e=""])=>{let t=ol([n]);return e?(e=e.toLowerCase(),r=>t(r)&&r.toLowerCase().endsWith(e)):t},Ic=([n,e=""])=>{let t=ll([n]);return e?(e=e.toLowerCase(),r=>t(r)&&r.toLowerCase().endsWith(e)):t},Nc=([n,e=""])=>{let t=ll([n]);return e?r=>t(r)&&r.endsWith(e):t},Tc=([n,e=""])=>{let t=ol([n]);return e?r=>t(r)&&r.endsWith(e):t},ol=([n])=>{let e=n.length;return t=>t.length===e&&!t.startsWith(".")},ll=([n])=>{let e=n.length;return t=>t.length===e&&t!=="."&&t!==".."},al=typeof process=="object"&&process?typeof process.env=="object"&&process.env&&process.env.__MINIMATCH_TESTING_PLATFORM__||process.platform:"posix",nl={win32:{sep:"\\"},posix:{sep:"/"}},Rc=al==="win32"?nl.win32.sep:nl.posix.sep;Z.sep=Rc;var oe=Symbol("globstar **");Z.GLOBSTAR=oe;var Ac="[^/]",Dc=Ac+"*?",Mc="(?:(?!(?:\\/|^)(?:\\.{1,2})($|\\/)).)*?",Pc="(?:(?!(?:\\/|^)\\.).)*?",Fc=(n,e={})=>t=>Z(t,n,e);Z.filter=Fc;var se=(n,e={})=>Object.assign({},n,e),Uc=n=>{if(!n||typeof n!="object"||!Object.keys(n).length)return Z;let e=Z;return Object.assign((r,i,s={})=>e(r,i,se(n,s)),{Minimatch:class extends e.Minimatch{constructor(i,s={}){super(i,se(n,s))}static defaults(i){return e.defaults(se(n,i)).Minimatch}},AST:class extends e.AST{constructor(i,s,o={}){super(i,s,se(n,o))}static fromGlob(i,s={}){return e.AST.fromGlob(i,se(n,s))}},unescape:(r,i={})=>e.unescape(r,se(n,i)),escape:(r,i={})=>e.escape(r,se(n,i)),filter:(r,i={})=>e.filter(r,se(n,i)),defaults:r=>e.defaults(se(n,r)),makeRe:(r,i={})=>e.makeRe(r,se(n,i)),braceExpand:(r,i={})=>e.braceExpand(r,se(n,i)),match:(r,i,s={})=>e.match(r,i,se(n,s)),sep:e.sep,GLOBSTAR:oe})};Z.defaults=Uc;var fl=(n,e={})=>(Tt(n),e.nobrace||!/\{(?:(?!\{).)*\}/.test(n)?[n]:(0,sl.default)(n));Z.braceExpand=fl;var kc=(n,e={})=>new it(n,e).makeRe();Z.makeRe=kc;var Bc=(n,e,t={})=>{let r=new it(e,t);return n=n.filter(i=>r.match(i)),r.options.nonull&&!n.length&&n.push(e),n};Z.match=Bc;var il=/[?*]|[+@!]\(.*?\)|\[|\]/,zc=n=>n.replace(/[-[\]{}()*+?.,\\^$|#\s]/g,"\\$&"),it=class{options;set;pattern;windowsPathsNoEscape;nonegate;negate;comment;empty;preserveMultipleSlashes;partial;globSet;globParts;nocase;isWindows;platform;windowsNoMagicRoot;regexp;constructor(e,t={}){Tt(e),t=t||{},this.options=t,this.pattern=e,this.platform=t.platform||al,this.isWindows=this.platform==="win32",this.windowsPathsNoEscape=!!t.windowsPathsNoEscape||t.allowWindowsEscape===!1,this.windowsPathsNoEscape&&(this.pattern=this.pattern.replace(/\\/g,"/")),this.preserveMultipleSlashes=!!t.preserveMultipleSlashes,this.regexp=null,this.negate=!1,this.nonegate=!!t.nonegate,this.comment=!1,this.empty=!1,this.partial=!!t.partial,this.nocase=!!this.options.nocase,this.windowsNoMagicRoot=t.windowsNoMagicRoot!==void 0?t.windowsNoMagicRoot:!!(this.isWindows&&this.nocase),this.globSet=[],this.globParts=[],this.set=[],this.make()}hasMagic(){if(this.options.magicalBraces&&this.set.length>1)return!0;for(let e of this.set)for(let t of e)if(typeof t!="string")return!0;return!1}debug(...e){}make(){let e=this.pattern,t=this.options;if(!t.nocomment&&e.charAt(0)==="#"){this.comment=!0;return}if(!e){this.empty=!0;return}this.parseNegate(),this.globSet=[...new Set(this.braceExpand())],t.debug&&(this.debug=(...s)=>console.error(...s)),this.debug(this.pattern,this.globSet);let r=this.globSet.map(s=>this.slashSplit(s));this.globParts=this.preprocess(r),this.debug(this.pattern,this.globParts);let i=this.globParts.map((s,o,a)=>{if(this.isWindows&&this.windowsNoMagicRoot){let l=s[0]===""&&s[1]===""&&(s[2]==="?"||!il.test(s[2]))&&!il.test(s[3]),f=/^[a-z]:/i.test(s[0]);if(l)return[...s.slice(0,4),...s.slice(4).map(u=>this.parse(u))];if(f)return[s[0],...s.slice(1).map(u=>this.parse(u))]}return s.map(l=>this.parse(l))});if(this.debug(this.pattern,i),this.set=i.filter(s=>s.indexOf(!1)===-1),this.isWindows)for(let s=0;s=2?(e=this.firstPhasePreProcess(e),e=this.secondPhasePreProcess(e)):t>=1?e=this.levelOneOptimize(e):e=this.adjascentGlobstarOptimize(e),e}adjascentGlobstarOptimize(e){return e.map(t=>{let r=-1;for(;(r=t.indexOf("**",r+1))!==-1;){let i=r;for(;t[i+1]==="**";)i++;i!==r&&t.splice(r,i-r)}return t})}levelOneOptimize(e){return e.map(t=>(t=t.reduce((r,i)=>{let s=r[r.length-1];return i==="**"&&s==="**"?r:i===".."&&s&&s!==".."&&s!=="."&&s!=="**"?(r.pop(),r):(r.push(i),r)},[]),t.length===0?[""]:t))}levelTwoFileOptimize(e){Array.isArray(e)||(e=this.slashSplit(e));let t=!1;do{if(t=!1,!this.preserveMultipleSlashes){for(let i=1;ii&&r.splice(i+1,o-i);let a=r[i+1],l=r[i+2],f=r[i+3];if(a!==".."||!l||l==="."||l===".."||!f||f==="."||f==="..")continue;t=!0,r.splice(i,1);let u=r.slice(0);u[i]="**",e.push(u),i--}if(!this.preserveMultipleSlashes){for(let o=1;ot.length)}partsMatch(e,t,r=!1){let i=0,s=0,o=[],a="";for(;iI?t=t.slice(L):I>L&&(e=e.slice(I)))}}let{optimizationLevel:s=1}=this.options;s>=2&&(e=this.levelTwoFileOptimize(e)),this.debug("matchOne",this,{file:e,pattern:t}),this.debug("matchOne",e.length,t.length);for(var o=0,a=0,l=e.length,f=t.length;o>> no match, partial?`,e,c,t,d),c===l))}let p;if(typeof u=="string"?(p=h===u,this.debug("string match",u,h,p)):(p=u.test(h),this.debug("pattern match",u,h,p)),!p)return!1}if(o===l&&a===f)return!0;if(o===l)return r;if(a===f)return o===l-1&&e[o]==="";throw new Error("wtf?")}braceExpand(){return fl(this.pattern,this.options)}parse(e){Tt(e);let t=this.options;if(e==="**")return oe;if(e==="")return"";let r,i=null;(r=e.match(xc))?i=t.dot?bc:Cc:(r=e.match(dc))?i=(t.nocase?t.dot?_c:gc:t.dot?mc:pc)(r[1]):(r=e.match(Lc))?i=(t.nocase?t.dot?Ic:Oc:t.dot?Nc:Tc)(r):(r=e.match(Ec))?i=t.dot?yc:wc:(r=e.match(Sc))&&(i=vc);let s=nt.fromGlob(e,this.options).toMMPattern();return i&&typeof s=="object"&&Reflect.defineProperty(s,"test",{value:i}),s}makeRe(){if(this.regexp||this.regexp===!1)return this.regexp;let e=this.set;if(!e.length)return this.regexp=!1,this.regexp;let t=this.options,r=t.noglobstar?Dc:t.dot?Mc:Pc,i=new Set(t.nocase?["i"]:[]),s=e.map(l=>{let f=l.map(u=>{if(u instanceof RegExp)for(let h of u.flags.split(""))i.add(h);return typeof u=="string"?zc(u):u===oe?oe:u._src});return f.forEach((u,h)=>{let c=f[h+1],d=f[h-1];u!==oe||d===oe||(d===void 0?c!==void 0&&c!==oe?f[h+1]="(?:\\/|"+r+"\\/)?"+c:f[h]=r:c===void 0?f[h-1]=d+"(?:\\/|"+r+")?":c!==oe&&(f[h-1]=d+"(?:\\/|\\/"+r+"\\/)"+c,f[h+1]=oe))}),f.filter(u=>u!==oe).join("/")}).join("|"),[o,a]=e.length>1?["(?:",")"]:["",""];s="^"+o+s+a+"$",this.negate&&(s="^(?!"+s+").+$");try{this.regexp=new RegExp(s,[...i].join(""))}catch{this.regexp=!1}return this.regexp}slashSplit(e){return this.preserveMultipleSlashes?e.split("/"):this.isWindows&&/^\/\/[^\/]+/.test(e)?["",...e.split(/\/+/)]:e.split(/\/+/)}match(e,t=this.partial){if(this.debug("match",e,this.pattern),this.comment)return!1;if(this.empty)return e==="";if(e==="/"&&t)return!0;let r=this.options;this.isWindows&&(e=e.split("\\").join("/"));let i=this.slashSplit(e);this.debug(this.pattern,"split",i);let s=this.set;this.debug(this.pattern,"set",s);let o=i[i.length-1];if(!o)for(let a=i.length-2;!o&&a>=0;a--)o=i[a];for(let a=0;ae[_l[n]](),Hc=n=>n instanceof URL?(0,gl.fileURLToPath)(n):n;function Rn(n,{cwd:e=pl.default.cwd(),type:t="file",allowSymlinks:r=!0}={}){$c(t),e=Hc(e);let i=r?cr.default.statSync:cr.default.lstatSync;for(let s of n)try{let o=i(ml.default.resolve(e,s),{throwIfNoEntry:!1});if(!o)continue;if(Vc(t,o))return s}catch{}}var El=require("node:url");function An(n){return n instanceof URL?(0,El.fileURLToPath)(n):n}var Zc=Symbol("findUpStop");function Yc(n,e={}){let t=st.default.resolve(An(e.cwd)??""),{root:r}=st.default.parse(t),i=st.default.resolve(t,An(e.stopAt)??r),s=e.limit??Number.POSITIVE_INFINITY,o=[n].flat(),a=f=>{if(typeof n!="function")return Rn(o,f);let u=n(f.cwd);return typeof u=="string"?Rn([u],f):u},l=[];for(;;){let f=a({...e,cwd:t});if(f===Zc||(f&&l.push(st.default.resolve(t,f)),t===i||l.length>=s))break;t=st.default.dirname(t)}return l}function wl(n,e={}){return Yc(n,{...e,limit:1})[0]}var Jl=j(zl()),Ql=j(Vl());var vr=j(require("node:process"),1),Zl=j(require("node:os"),1),Yn=j(require("node:tty"),1);function ae(n,e=globalThis.Deno?globalThis.Deno.args:vr.default.argv){let t=n.startsWith("-")?"":n.length===1?"-":"--",r=e.indexOf(t+n),i=e.indexOf("--");return r!==-1&&(i===-1||r=2,has16m:n>=3}}function ch(n,{streamIsTTY:e,sniffFlags:t=!0}={}){let r=fh();r!==void 0&&(Sr=r);let i=t?Sr:r;if(i===0)return 0;if(t){if(ae("color=16m")||ae("color=full")||ae("color=truecolor"))return 3;if(ae("color=256"))return 2}if("TF_BUILD"in k&&"AGENT_NAME"in k)return 1;if(n&&!e&&i===void 0)return 0;let s=i||0;if(k.TERM==="dumb")return s;if(vr.default.platform==="win32"){let o=Zl.default.release().split(".");return Number(o[0])>=10&&Number(o[2])>=10586?Number(o[2])>=14931?3:2:1}if("CI"in k)return["GITHUB_ACTIONS","GITEA_ACTIONS","CIRCLECI"].some(o=>o in k)?3:["TRAVIS","APPVEYOR","GITLAB_CI","BUILDKITE","DRONE"].some(o=>o in k)||k.CI_NAME==="codeship"?1:s;if("TEAMCITY_VERSION"in k)return/^(9\.(0*[1-9]\d*)\.|\d{2,}\.)/.test(k.TEAMCITY_VERSION)?1:0;if(k.COLORTERM==="truecolor"||k.TERM==="xterm-kitty"||k.TERM==="xterm-ghostty"||k.TERM==="wezterm")return 3;if("TERM_PROGRAM"in k){let o=Number.parseInt((k.TERM_PROGRAM_VERSION||"").split(".")[0],10);switch(k.TERM_PROGRAM){case"iTerm.app":return o>=3?3:2;case"Apple_Terminal":return 2}}return/-256(color)?$/i.test(k.TERM)?2:/^screen|^xterm|^vt100|^vt220|^rxvt|color|ansi|cygwin|linux/i.test(k.TERM)||"COLORTERM"in k?1:s}function Hl(n,e={}){let t=ch(n,{streamIsTTY:n&&n.isTTY,...e});return uh(t)}var hh={stdout:Hl({isTTY:Yn.default.isatty(1)}),stderr:Hl({isTTY:Yn.default.isatty(2)})},Yl=hh;0&&(module.exports={StreamZip,WebSocket,ZipFile,convertSourceMap,decode,diffSequence,findUpSync,minimatch,parseCss,supportsColor}); diff --git a/node_modules/monocart-coverage-reports/lib/platform/concurrency.js b/node_modules/monocart-coverage-reports/lib/platform/concurrency.js new file mode 100644 index 0000000..0a280d7 --- /dev/null +++ b/node_modules/monocart-coverage-reports/lib/platform/concurrency.js @@ -0,0 +1,74 @@ +class Concurrency { + + constructor(maxCount = 10) { + this.maxCount = maxCount; + this.list = []; + } + + addItem(item) { + this.list.push(item); + } + + addList(list) { + this.list = this.list.concat(list); + } + + start(handler) { + // must be async function + if (typeof handler !== 'function') { + return; + } + this.handler = handler; + this.count = 0; + return new Promise((resolve) => { + this.resolve = resolve; + this.next(); + }); + } + + next() { + // console.log(`list: ${this.list.length} count: ${this.count}`); + + // if has clear + if (!this.resolve) { + return; + } + + if (!this.list.length) { + // no list but has in progress count + if (this.count > 0) { + return; + } + // all finish + this.resolve(); + this.clear(); + return; + } + + // out of concurrency count, just wait + if (this.count >= this.maxCount) { + return; + } + + const item = this.list.shift(); + this.count += 1; + + // async handler + this.handler(item).finally(() => { + this.count -= 1; + this.next(); + }); + + this.next(); + } + + clear() { + this.list = []; + this.handler = null; + this.count = 0; + this.resolve = null; + } + +} + +module.exports = Concurrency; diff --git a/node_modules/monocart-coverage-reports/lib/platform/share.js b/node_modules/monocart-coverage-reports/lib/platform/share.js new file mode 100644 index 0000000..ef5fb6e --- /dev/null +++ b/node_modules/monocart-coverage-reports/lib/platform/share.js @@ -0,0 +1,538 @@ +const Util = { + + hasOwn: function(obj, key) { + return Object.prototype.hasOwnProperty.call(obj, key); + }, + + isNull: function(input) { + if (input === null || typeof input === 'undefined') { + return true; + } + return false; + }, + + uid: function(len = 20, prefix = '') { + const dict = '0123456789abcdefghijklmnopqrstuvwxyz'; + const dictLen = dict.length; + let str = prefix; + while (len--) { + str += dict[Math.random() * dictLen | 0]; + } + return str; + }, + + zero: function(s, l = 2) { + s = `${s}`; + return s.padStart(l, '0'); + }, + + isNum: function(num) { + if (typeof num !== 'number' || isNaN(num)) { + return false; + } + const isInvalid = function(n) { + if (n === Number.MAX_VALUE || n === Number.MIN_VALUE || n === Number.NEGATIVE_INFINITY || n === Number.POSITIVE_INFINITY) { + return true; + } + return false; + }; + if (isInvalid(num)) { + return false; + } + return true; + }, + + toNum: function(num, toInt) { + if (typeof (num) !== 'number') { + num = parseFloat(num); + } + if (isNaN(num)) { + num = 0; + } + if (toInt) { + num = Math.round(num); + } + return num; + }, + + isList: function(data) { + if (data && data instanceof Array && data.length > 0) { + return true; + } + return false; + }, + + toList: function(data, separator) { + if (data instanceof Array) { + return data; + } + if (typeof data === 'string' && (typeof separator === 'string' || separator instanceof RegExp)) { + return data.split(separator).map((str) => str.trim()).filter((str) => str); + } + if (typeof data === 'undefined' || data === null) { + return []; + } + return [data]; + }, + + forEach: function(rootList, callback) { + const isBreak = (res) => { + return res === 'break' || res === false; + }; + const forList = (list, parent) => { + if (!Util.isList(list)) { + return; + } + for (const item of list) { + const result = callback(item, parent); + if (isBreak(result)) { + return result; + } + const subResult = forList(item.subs, item); + if (isBreak(subResult)) { + return subResult; + } + } + }; + forList(rootList); + }, + + // \ to / + formatPath: function(str) { + if (str) { + str = str.replace(/\\/g, '/'); + } + return str; + }, + + getCurrentTrendInfo: (data) => { + + const { + date, duration, summary + } = data; + + const info = { + date, + duration + }; + + Object.keys(summary).forEach((k) => { + const item = summary[k]; + info[k] = item.value; + }); + + return info; + }, + + isTagItem: (item) => { + if (item.type === 'case' || (item.type === 'suite' && item.suiteType === 'describe')) { + return true; + } + return false; + }, + + delay: function(ms) { + return new Promise((resolve) => { + if (ms) { + setTimeout(resolve, ms); + } else { + setImmediate(resolve); + } + }); + }, + + // ============================================================================= + + getMetrics: (metrics, type) => { + const istanbulMetrics = ['statements', 'branches', 'functions', 'lines']; + const v8Metrics = ['bytes'].concat(istanbulMetrics); + const allMetrics = type === 'istanbul' ? istanbulMetrics : v8Metrics; + let list = allMetrics; + if (Util.isList(metrics)) { + const newList = list.filter((k) => metrics.includes(k)); + if (newList.length) { + list = newList; + } + } + return list; + }, + + generatePercentChart: function(percent) { + return `
`; + }, + + getStatus: (value, watermarks) => { + if (!watermarks) { + return 'unknown'; + } + if (value < watermarks[0]) { + return 'low'; + } + if (value < watermarks[1]) { + return 'medium'; + } + return 'high'; + }, + + isJsonType: (contentType) => { + if (contentType) { + if (contentType === 'application/json' || contentType === 'json') { + return true; + } + } + return false; + }, + + isMarkdownType: (contentType) => { + if (contentType) { + if (contentType === 'text/markdown' || contentType === 'markdown') { + return true; + } + } + return false; + }, + + isTextType: (contentType) => { + if (contentType) { + if (contentType.startsWith('text')) { + return true; + } + if (Util.isMarkdownType(contentType)) { + return true; + } + if (Util.isJsonType(contentType)) { + return true; + } + } + return false; + }, + + isBlank: (codeStr) => { + if (typeof codeStr === 'string') { + const blankBlock = /\S/; + return !blankBlock.test(codeStr); + } + return false; + }, + + findInRanges: (startPos, endPos, rangeList, startKey = 'start', endKey = 'end') => { + if (!Util.isList(rangeList)) { + return; + } + + // rangeList should be sorted by startKey, but seems useless here + const list = rangeList.filter((it) => startPos >= it[startKey] && endPos <= it[endKey]); + if (!list.length) { + return; + } + + // could be multiple results, but seems no case for now + // if (list.length > 1) { + // console.log('==============', list); + // } + + return list[0]; + }, + + getRangeLines: (sLoc, eLoc) => { + + const lines = []; + + // invalid location order + if (sLoc.line > eLoc.line) { + return lines; + } + + // nothing middle + if (sLoc.line === eLoc.line && sLoc.column >= eLoc.column) { + return lines; + } + + const addStart = () => { + + // nothing start + if (sLoc.column >= sLoc.length) { + return; + } + + const entire = sLoc.column <= sLoc.indent; + lines.push({ + line: sLoc.line, + entire, + pieces: { + start: sLoc.column, + end: sLoc.length + } + }); + }; + + const addMiddle = () => { + + const start = sLoc.column <= sLoc.indent; + const end = Util.isBlank(eLoc.text.slice(eLoc.column)); + const entire = start && end; + // same line + lines.push({ + line: sLoc.line, + entire, + pieces: { + start: sLoc.column, + end: eLoc.column + } + }); + }; + + const addEnd = () => { + + // nothing end + if (eLoc.column === 0) { + return; + } + + // pieces in indent, ignored + if (eLoc.column <= eLoc.indent) { + return; + } + + const rightText = eLoc.text.slice(eLoc.column); + + // right text is blank or only ";" (few cases) + const entire = Util.isBlank(rightText) || rightText.trim() === ';'; + lines.push({ + line: eLoc.line, + entire, + pieces: { + start: eLoc.indent, + end: eLoc.column + } + }); + }; + + // same line, single line + if (sLoc.line === eLoc.line) { + + addMiddle(); + + } else { + // multiple lines + + addStart(); + + // always entire for middle lines + const lineStart = sLoc.line + 1; + const lineEnd = eLoc.line; + if (lineEnd > lineStart) { + for (let i = lineStart; i < lineEnd; i++) { + lines.push({ + line: i, + entire: true + // no pieces for entire line + }); + } + } + + // check end + addEnd(); + } + + return lines; + }, + + initLineCoverage: (lineItem) => { + lineItem.coveredCount = 1; + lineItem.uncoveredEntire = null; + lineItem.uncoveredPieces = []; + }, + + updateLinesCoverage: (lines, count, lineMap) => { + lines.forEach((it) => { + const lineItem = lineMap.get(it.line); + if (!lineItem) { + // not found line, could be comment or blank line + return; + } + + if (lineItem.ignored) { + return; + } + + it.count = count; + + // default is covered, so only focus on + // 1, biggest covered count + // 2, uncovered entire and pieces + if (count > 0) { + lineItem.coveredCount = Math.max(lineItem.coveredCount, count); + return; + } + + if (it.entire) { + lineItem.uncoveredEntire = it; + } else { + lineItem.uncoveredPieces.push(it); + } + + }); + + }, + + // ============================================================================= + // svg + + dFixed: (num, fixed = 1) => { + if (Number.isInteger(num)) { + return num; + } + return Util.toNum(Util.toNum(num).toFixed(fixed)); + }, + + pxFixed: (num) => { + const floor = Math.floor(num); + if (num < floor + 0.5) { + return floor + 0.5; + } + return floor + 1.5; + }, + + point: (px, py) => { + return `${Util.dFixed(px)},${Util.dFixed(py)}`; + }, + + capitalizeFirstLetter: (string) => { + return string.charAt(0).toUpperCase() + string.slice(1); + }, + + jsonParse: function(str) { + + if (typeof str !== 'string') { + return null; + } + + if (!str) { + return null; + } + + let json = null; + + // remove BOM \ufeff + // str = str.replace(/^\uFEFF/, ''); + + try { + json = JSON.parse(str); + } catch (e) { + // console.log(e); + } + + return json; + }, + + // ============================================================================= + // formatter + + // number + NF: function(v) { + if (typeof v === 'number' && v) { + return v.toLocaleString(); + } + return v; + }, + + // percent + PF: function(v, t = 1, digits = 1, unit = '%', space = '') { + v = Util.toNum(v); + t = Util.toNum(t); + let per = 0; + if (t) { + per = v / t; + } + const perStr = (per * 100).toFixed(digits); + if (unit) { + return perStr + space + unit; + } + return parseFloat(perStr); + }, + + PSF: function(v, t = 1, digits = 1) { + return Util.PF(v, t, digits, '%', ' '); + }, + + PNF: function(v, t = 1, digits = 1) { + return Util.PF(v, t, digits, ''); + }, + + // byte + BF: function(v, places = 1, space = '') { + v = Util.toNum(v, true); + if (v === 0) { + return `0${space}B`; + } + let prefix = ''; + if (v < 0) { + v = Math.abs(v); + prefix = '-'; + } + + const base = 1024; + const units = ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB']; + for (let i = 0, l = units.length; i < l; i++) { + const min = Math.pow(base, i); + const max = Math.pow(base, i + 1); + if (v > min && v < max) { + const unit = units[i]; + v = prefix + parseFloat((v / min).toFixed(places)) + space + unit; + break; + } + } + return v; + }, + + BSF: function(v, places = 1) { + return Util.BF(v, places, ' '); + }, + + // time + TF: function(v, space = '') { + const ms = Util.toNum(v, true); + + if (ms < 1000) { + return `${ms}${space}ms`; + } + + if (ms < 60 * 1000) { + const ss = parseFloat((ms / 1000).toFixed(1)); + return `${ss}${space}s`; + } + + const s = Math.round(ms / 1000); + + const m = 60; + const h = m * 60; + const d = h * 24; + + if (s < h) { + const minutes = Math.floor(s / m); + const seconds = s - minutes * m; + return `${minutes}${space}m ${seconds}${space}s`; + } + + if (s < d) { + const hours = Math.floor(s / h); + const minutes = Math.floor((s - hours * h) / m); + const seconds = s - hours * h - minutes * m; + return `${hours}${space}h ${minutes}${space}m ${seconds}${space}s`; + } + + const days = Math.floor(s / d); + const hours = Math.floor((s - days * d) / h); + const minutes = Math.floor((s - days * d - hours * h) / m); + const seconds = s - days * d - hours * h - minutes * m; + return `${days}${space}d ${hours}${space}h ${minutes}${space}m ${seconds}${space}s`; + }, + + TSF: function(v) { + return Util.TF(v, ' '); + } +}; + + +module.exports = Util; diff --git a/node_modules/monocart-coverage-reports/lib/register/hooks.js b/node_modules/monocart-coverage-reports/lib/register/hooks.js new file mode 100644 index 0000000..64a1cf5 --- /dev/null +++ b/node_modules/monocart-coverage-reports/lib/register/hooks.js @@ -0,0 +1,58 @@ +const fs = require('fs'); +const path = require('path'); +const Util = require('../utils/util.js'); +const { convertSourceMap } = require('../packages/monocart-coverage-vendor.js'); + +function saveFile(url, source, dir) { + if (!fs.existsSync(dir)) { + fs.mkdirSync(dir, { + recursive: true + }); + } + + const id = Util.calculateSha1(url + source); + const filePath = path.resolve(dir, `source-${id}.json`); + if (!fs.existsSync(filePath)) { + fs.writeFileSync(filePath, JSON.stringify({ + url, + source + })); + } + +} + +function saveSource(url, loaded, dir) { + + // filter node modules + if (url.startsWith('node:')) { + return; + } + + const { source, format } = loaded; + if (typeof source !== 'string' || !['module', 'commonjs'].includes(format)) { + // no source or wrong format + return; + } + + if (!convertSourceMap.mapFileCommentRegex.test(source)) { + // no sourcemap + return; + } + + saveFile(url, source, dir); + +} + +async function load(url, context, nextLoad) { + const loaded = await nextLoad(url, context); + const dir = process.env.NODE_V8_COVERAGE; + if (dir) { + // only for coverage enabled + saveSource(url, loaded, dir); + } + return loaded; +} + +module.exports = { + load +}; diff --git a/node_modules/monocart-coverage-reports/lib/register/hooks.mjs b/node_modules/monocart-coverage-reports/lib/register/hooks.mjs new file mode 100644 index 0000000..53e4357 --- /dev/null +++ b/node_modules/monocart-coverage-reports/lib/register/hooks.mjs @@ -0,0 +1,3 @@ +import { load } from './hooks.js'; + +export { load }; diff --git a/node_modules/monocart-coverage-reports/lib/register/register.js b/node_modules/monocart-coverage-reports/lib/register/register.js new file mode 100644 index 0000000..87a14e1 --- /dev/null +++ b/node_modules/monocart-coverage-reports/lib/register/register.js @@ -0,0 +1,4 @@ +const { register } = require('module'); +const { pathToFileURL } = require('url'); + +register('./hooks.js', pathToFileURL(__filename)); diff --git a/node_modules/monocart-coverage-reports/lib/register/register.mjs b/node_modules/monocart-coverage-reports/lib/register/register.mjs new file mode 100644 index 0000000..bee37a5 --- /dev/null +++ b/node_modules/monocart-coverage-reports/lib/register/register.mjs @@ -0,0 +1,3 @@ +import { register } from 'module'; + +register('./hooks.mjs', import.meta.url); diff --git a/node_modules/monocart-coverage-reports/lib/utils/dedupe.js b/node_modules/monocart-coverage-reports/lib/utils/dedupe.js new file mode 100644 index 0000000..8a74ece --- /dev/null +++ b/node_modules/monocart-coverage-reports/lib/utils/dedupe.js @@ -0,0 +1,123 @@ +/** + * The ranges are first ordered by ascending `startOffset` and then by descending `endOffset`. + * This corresponds to a pre-order tree traversal. + */ + +const sortRanges = (ranges) => { + ranges.sort((a, b) => { + if (a.start === b.start) { + return b.end - a.end; + } + return a.start - b.start; + }); +}; + +const filterRanges = (ranges) => { + // remove start = end + return ranges.filter((range) => range.start < range.end); +}; + +// apply directly to css ranges +const dedupeFlatRanges = (ranges) => { + + ranges = filterRanges(ranges); + + if (ranges.length < 2) { + return ranges; + } + + sortRanges(ranges); + + ranges.reduce((prevRange, range) => { + + // same start + if (range.start === prevRange.start) { + range.dedupe = true; + // equal prev + if (range.end === prevRange.end) { + return prevRange; + } + + // less than prev end after new sort + + return prevRange; + } + + // already in the range + if (range.end <= prevRange.end) { + range.dedupe = true; + return prevRange; + } + + // collected, update the end + if (range.start <= prevRange.end) { + range.dedupe = true; + prevRange.end = range.end; + return prevRange; + } + + return range; + }); + + ranges = ranges.filter((it) => !it.dedupe); + + return ranges; +}; + +const mergeRangesWith = (ranges, comparer, handler) => { + + // ranges format + // { start: 0, end: 6, ... } + + ranges = filterRanges(ranges); + + if (ranges.length < 2) { + return ranges; + } + + sortRanges(ranges); + + let hasDedupe = false; + + // merge count for same range + ranges.reduce((lastRange, range) => { + if (comparer(lastRange, range)) { + range.dedupe = true; + + handler(lastRange, range); + + hasDedupe = true; + + return lastRange; + } + return range; + }); + + if (hasDedupe) { + // console.log(ranges); + ranges = ranges.filter((it) => !it.dedupe); + } + + // console.log('ranges length after', ranges.length); + + return ranges; +}; + +// apply to js count ranges +const dedupeCountRanges = (ranges) => { + const comparer = (lastRange, range) => { + return lastRange.start === range.start && lastRange.end === range.end; + }; + const handler = (lastRange, range) => { + lastRange.count += range.count; + }; + return mergeRangesWith(ranges, comparer, handler); +}; + + +module.exports = { + sortRanges, + dedupeFlatRanges, + mergeRangesWith, + dedupeCountRanges +}; diff --git a/node_modules/monocart-coverage-reports/lib/utils/gc.js b/node_modules/monocart-coverage-reports/lib/utils/gc.js new file mode 100644 index 0000000..316337d --- /dev/null +++ b/node_modules/monocart-coverage-reports/lib/utils/gc.js @@ -0,0 +1,9 @@ +const v8 = require('node:v8'); +const vm = require('node:vm'); + +if (typeof global.gc !== 'function') { + v8.setFlagsFromString('--expose_gc'); + global.gc = vm.runInNewContext('gc'); +} + +module.exports = global.gc; diff --git a/node_modules/monocart-coverage-reports/lib/utils/markdown.js b/node_modules/monocart-coverage-reports/lib/utils/markdown.js new file mode 100644 index 0000000..d29d708 --- /dev/null +++ b/node_modules/monocart-coverage-reports/lib/utils/markdown.js @@ -0,0 +1,132 @@ +const os = require('os'); + +const renderLine = (ls, padding) => { + const spacing = ''.padEnd(padding, ' '); + const line = ls.join(`${spacing}|${spacing}`); + return `|${spacing}${line}${spacing}|`; +}; + +const renderCell = (cellValue, column) => { + + // To include a pipe | as content within your cell, use a \ before the pipe: + cellValue = cellValue.split(/\\?\|/g).join('\\|'); + const valueWidth = cellValue.length; + const width = column.width; + + if (width <= valueWidth) { + return cellValue; + } + + const spacingWidth = width - valueWidth; + const spacing = ''.padEnd(spacingWidth, ' '); + + const align = column.align; + + if (align === 'right') { + return spacing + cellValue; + } + + if (align === 'center') { + const l = Math.round(spacingWidth * 0.5); + const r = spacingWidth - l; + const spacingL = ''.padEnd(l, ' '); + const spacingR = ''.padEnd(r, ' '); + return spacingL + cellValue + spacingR; + + } + + return cellValue + spacing; +}; + +const renderHyphen = (column) => { + const width = column.width; + const align = column.align; + if (align === 'right') { + return ':'.padStart(width, '-'); + } + if (align === 'center') { + const hyphen = ''.padEnd(width - 2, '-'); + return `:${hyphen}:`; + } + // default to left + return ':'.padEnd(width, '-'); +}; + +const markdownGrid = (data) => { + + const options = { + name: '', + padding: 1, + nullPlaceholder: '', + ... data.options + }; + + const padding = options.padding; + + // console.log(data, options); + + const lines = []; + + if (options.name) { + lines.push(`## ${options.name}`); + } + + // init columns + const columns = data.columns.map((item) => { + if (typeof item === 'string') { + item = { + name: item + }; + } + const column = { + ... item + }; + column.name = `${column.name}`; + if (typeof column.width !== 'number') { + column.width = column.name.length; + } + column.width = Math.max(column.width, 3); + return column; + }); + + // header + const headers = []; + columns.forEach((column) => { + headers.push(renderCell(column.name, column)); + }); + lines.push(renderLine(headers, padding)); + + const hyphens = []; + columns.forEach((column) => { + hyphens.push(renderHyphen(column)); + }); + lines.push(renderLine(hyphens, padding)); + + // rows + data.rows.forEach((row) => { + const cells = []; + columns.forEach((column, i) => { + let cellValue = ''; + if (Array.isArray(row)) { + cellValue += row[i]; + } else { + let v = row[column.id]; + if (typeof v === 'undefined' || v === null) { + v = options.nullPlaceholder; + } + if (column.formatter) { + v = column.formatter(v, row, column); + } + cellValue += v; + } + cells.push(renderCell(cellValue, column)); + }); + lines.push(renderLine(cells, padding)); + }); + + return lines.join(os.EOL) + os.EOL; + +}; + + +module.exports = markdownGrid; diff --git a/node_modules/monocart-coverage-reports/lib/utils/merge/merge.js b/node_modules/monocart-coverage-reports/lib/utils/merge/merge.js new file mode 100644 index 0000000..098983c --- /dev/null +++ b/node_modules/monocart-coverage-reports/lib/utils/merge/merge.js @@ -0,0 +1,439 @@ +/** + * The `mergeV8Coverage` was extracted from following repos for fixing several issues + * https://github.com/bcoe/v8-coverage + * https://github.com/demurgos/v8-coverage + */ + +const RangeTree = require('./range-tree.js'); + + +/** + * Compares two range coverages. + * + * The ranges are first ordered by ascending `startOffset` and then by + * descending `endOffset`. + * This corresponds to a pre-order tree traversal. + */ +function compareRangeCovs(a, b) { + if (a.startOffset !== b.startOffset) { + return a.startOffset - b.startOffset; + } + return b.endOffset - a.endOffset; +} + +/** + * Compares two function coverages. + * + * The result corresponds to the comparison of the root ranges. + */ +function compareFunctionCovs(a, b) { + return compareRangeCovs(a.ranges[0], b.ranges[0]); +} + +/** + * @precodition `ranges` are well-formed and pre-order sorted + */ +function fromSortedRanges(ranges) { + let root; + // Stack of parent trees and parent counts. + const stack = []; + for (const range of ranges) { + const node = new RangeTree(range.startOffset, range.endOffset, range.count, []); + if (!root) { + root = node; + stack.push([node, range.count]); + continue; + } + let parent; + let parentCount; + while (true) { + [parent, parentCount] = stack[stack.length - 1]; + // assert: `top !== undefined` (the ranges are sorted) + if (range.startOffset < parent.end) { + break; + } else { + stack.pop(); + } + + // prevent crash when v8 incorrectly merges static_initializer's + if (stack.length === 0) { + break; + } + } + node.delta -= parentCount; + parent.children.push(node); + stack.push([node, range.count]); + } + return root; +} + +/** + * Normalizes a function coverage. + * + * Sorts the ranges (pre-order sort). + * TODO: Tree-based normalization of the ranges. + * + * @param funcCov Function coverage to normalize. + */ +function normalizeFunctionCov(funcCov) { + funcCov.ranges.sort(compareRangeCovs); + const tree = fromSortedRanges(funcCov.ranges); + tree.normalize(); + funcCov.ranges = tree.toRanges(); +} + +/** + * Normalizes a script coverage. + * + * Sorts the function by root range (pre-order sort). + * This does not normalize the function coverages. + * + * @param scriptCov Script coverage to normalize. + */ +function normalizeScriptCov(scriptCov) { + scriptCov.functions.sort(compareFunctionCovs); +} + + +/** + * Normalizes a script coverage deeply. + * + * Normalizes the function coverages deeply, then normalizes the script coverage + * itself. + * + * @param scriptCov Script coverage to normalize. + */ +function deepNormalizeScriptCov(scriptCov) { + for (const funcCov of scriptCov.functions) { + normalizeFunctionCov(funcCov); + } + normalizeScriptCov(scriptCov); +} + + +/** + * Returns a string representation of the root range of the function. + * + * This string can be used to match function with same root range. + * The string is derived from the start and end offsets of the root range of + * the function. + * This assumes that `ranges` is non-empty (true for valid function coverages). + * + * @param funcCov Function coverage with the range to stringify + * @internal + */ +function stringifyFunctionRootRange(funcCov) { + const rootRange = funcCov.ranges[0]; + return `${rootRange.startOffset.toString(10)};${rootRange.endOffset.toString(10)}`; +} + + +function insertChild(parentToNested, parentIndex, tree) { + let nested = parentToNested.get(parentIndex); + if (!nested) { + nested = []; + parentToNested.set(parentIndex, nested); + } + nested.push(tree); +} + +function nextChild(openRange, parentToNested) { + const matchingTrees = []; + + for (const nested of parentToNested.values()) { + if (nested.length === 1 && nested[0].start === openRange.start && nested[0].end === openRange.end) { + matchingTrees.push(nested[0]); + } else { + matchingTrees.push(new RangeTree( + openRange.start, + openRange.end, + 0, + nested + )); + } + } + parentToNested.clear(); + return mergeRangeTrees(matchingTrees); +} + +class StartEventQueue { + + constructor(queue) { + this.queue = queue; + this.nextIndex = 0; + this.pendingOffset = 0; + this.pendingTrees = null; + } + + setPendingOffset(offset) { + this.pendingOffset = offset; + } + + pushPendingTree(tree) { + if (this.pendingTrees === null) { + this.pendingTrees = []; + } + this.pendingTrees.push(tree); + } + + next() { + const pendingTrees = this.pendingTrees; + const nextEvent = this.queue[this.nextIndex]; + if (pendingTrees === null) { + this.nextIndex++; + return nextEvent; + } + if (!nextEvent) { + this.pendingTrees = null; + return { + offset: this.pendingOffset, + trees: pendingTrees + }; + } + if (this.pendingOffset < nextEvent.offset) { + this.pendingTrees = null; + return { + offset: this.pendingOffset, + trees: pendingTrees + }; + } + if (this.pendingOffset === nextEvent.offset) { + this.pendingTrees = null; + for (const tree of pendingTrees) { + nextEvent.trees.push(tree); + } + } + this.nextIndex++; + return nextEvent; + + + } +} + +function fromParentTrees(parentTrees) { + const startToTrees = new Map(); + for (const [parentIndex, parentTree] of parentTrees.entries()) { + for (const child of parentTree.children) { + let trees = startToTrees.get(child.start); + if (!trees) { + trees = []; + startToTrees.set(child.start, trees); + } + trees.push({ + parentIndex, + tree: child + }); + } + } + const queue = []; + for (const [startOffset, trees] of startToTrees) { + queue.push({ + offset: startOffset, + trees + }); + } + queue.sort((a, b) => { + return a.offset - b.offset; + }); + return new StartEventQueue(queue); +} + +// eslint-disable-next-line complexity +function mergeRangeTreeChildren(parentTrees) { + const result = []; + const startEventQueue = fromParentTrees(parentTrees); + const parentToNested = new Map(); + let openRange = null; + + while (true) { + const event = startEventQueue.next(); + if (!event) { + break; + } + + if (openRange !== null && openRange.end <= event.offset) { + result.push(nextChild(openRange, parentToNested)); + openRange = null; + } + + if (openRange === null) { + let openRangeEnd = event.offset + 1; + for (const { parentIndex, tree } of event.trees) { + openRangeEnd = Math.max(openRangeEnd, tree.end); + insertChild(parentToNested, parentIndex, tree); + } + startEventQueue.setPendingOffset(openRangeEnd); + openRange = { + start: event.offset, end: openRangeEnd + }; + } else { + for (const { parentIndex, tree } of event.trees) { + if (tree.end > openRange.end) { + const right = tree.split(openRange.end); + startEventQueue.pushPendingTree({ + parentIndex, + tree: right + }); + } + insertChild(parentToNested, parentIndex, tree); + } + } + } + if (openRange !== null) { + result.push(nextChild(openRange, parentToNested)); + } + + return result; +} + +/** + * @precondition Same `start` and `end` for all the trees + */ +function mergeRangeTrees(trees) { + if (trees.length <= 1) { + return trees[0]; + } + const first = trees[0]; + let delta = 0; + for (const tree of trees) { + delta += tree.delta; + } + const children = mergeRangeTreeChildren(trees); + return new RangeTree(first.start, first.end, delta, children); +} + +/** + * Merges a list of matching function coverages. + * + * Functions are matching if their root ranges have the same span. + * The result is normalized. + * The input values may be mutated, it is not safe to use them after passing + * them to this function. + * The computation is synchronous. + * + * @param funcCovs Function coverages to merge. + * @return Merged function coverage, or `undefined` if the input list was empty. + */ +function mergeFunctionCovs(funcCovs) { + if (funcCovs.length === 0) { + return; + } + + if (funcCovs.length === 1) { + const merged = funcCovs[0]; + normalizeFunctionCov(merged); + return merged; + } + + const first = funcCovs[0]; + const functionName = first.functionName; + // assert: `first.ranges.length > 0` + const startOffset = first.ranges[0].startOffset; + const endOffset = first.ranges[0].endOffset; + let count = 0; + + const trees = []; + for (const funcCov of funcCovs) { + // assert: `funcCov.ranges.length > 0` + // assert: `funcCov.ranges` is sorted + count += typeof funcCov.count === 'number' ? funcCov.count : funcCov.ranges[0].count; + if (funcCov.isBlockCoverage) { + trees.push(fromSortedRanges(funcCov.ranges)); + } + } + + let isBlockCoverage; + let ranges; + if (trees.length > 0) { + isBlockCoverage = true; + const mergedTree = mergeRangeTrees(trees); + mergedTree.normalize(); + ranges = mergedTree.toRanges(); + } else { + isBlockCoverage = false; + ranges = [{ + startOffset, + endOffset, + count + }]; + } + + const merged = { + functionName, + ranges, + isBlockCoverage + }; + if (count !== ranges[0].count) { + merged.count = count; + } + // assert: `merged` is normalized + return merged; +} + + +/** + * Merges a list of matching script coverages. + * + * Scripts are matching if they have the same `url`. + * The result is normalized. + * The input values may be mutated, it is not safe to use them after passing + * them to this function. + * The computation is synchronous. + * + * @param scriptCovs Process coverages to merge. + * @return Merged script coverage, or `undefined` if the input list was empty. + */ + +// eslint-disable-next-line complexity +function mergeV8Coverage(scriptCovs) { + if (!Array.isArray(scriptCovs)) { + return { + functions: [] + }; + } + + if (scriptCovs.length === 0) { + return { + functions: [] + }; + } + + if (scriptCovs.length === 1) { + const merged = scriptCovs[0]; + deepNormalizeScriptCov(merged); + return merged; + } + + + const rangeToFuncs = new Map(); + for (const scriptCov of scriptCovs) { + for (const funcCov of scriptCov.functions) { + const rootRange = stringifyFunctionRootRange(funcCov); + let funcCovs = rangeToFuncs.get(rootRange); + if (!funcCovs) { + funcCovs = []; + rangeToFuncs.set(rootRange, funcCovs); + } + funcCovs.push(funcCov); + } + } + + const functions = []; + for (const funcCovs of rangeToFuncs.values()) { + // assert: `funcCovs.length > 0` + const block = mergeFunctionCovs(funcCovs); + if (block) { + functions.push(block); + } + } + + const merged = { + functions + }; + normalizeScriptCov(merged); + return merged; +} + +module.exports = { + mergeV8Coverage +}; diff --git a/node_modules/monocart-coverage-reports/lib/utils/merge/range-tree.js b/node_modules/monocart-coverage-reports/lib/utils/merge/range-tree.js new file mode 100644 index 0000000..baffb48 --- /dev/null +++ b/node_modules/monocart-coverage-reports/lib/utils/merge/range-tree.js @@ -0,0 +1,123 @@ +class RangeTree { + + constructor( + start, + end, + delta, + children + ) { + this.start = start; + this.end = end; + this.delta = delta; + this.children = children; + } + + // eslint-disable-next-line complexity + normalize() { + const children = []; + let curEnd; + let head; + const tail = []; + for (const child of this.children) { + if (!head) { + head = child; + } else if (child.delta === head.delta && child.start === curEnd) { + tail.push(child); + } else { + endChain(); + head = child; + } + curEnd = child.end; + } + if (head) { + endChain(); + } + + if (children.length === 1) { + const child = children[0]; + if (child.start === this.start && child.end === this.end) { + this.delta += child.delta; + this.children = child.children; + // `.lazyCount` is zero for both (both are after normalization) + return; + } + } + + this.children = children; + + function endChain() { + if (tail.length !== 0) { + head.end = tail[tail.length - 1].end; + for (const tailTree of tail) { + for (const subChild of tailTree.children) { + subChild.delta += tailTree.delta - head.delta; + head.children.push(subChild); + } + } + tail.length = 0; + } + head.normalize(); + children.push(head); + } + } + + /** + * @precondition `tree.start < value && value < tree.end` + * @return RangeTree Right part + */ + split(value) { + let leftChildLen = this.children.length; + let mid; + + // TODO(perf): Binary search (check overhead) + for (let i = 0; i < this.children.length; i++) { + const child = this.children[i]; + if (child.start < value && value < child.end) { + mid = child.split(value); + leftChildLen = i + 1; + break; + } else if (child.start >= value) { + leftChildLen = i; + break; + } + } + + const rightLen = this.children.length - leftChildLen; + const rightChildren = this.children.splice(leftChildLen, rightLen); + if (mid) { + rightChildren.unshift(mid); + } + const result = new RangeTree( + value, + this.end, + this.delta, + rightChildren + ); + this.end = value; + return result; + } + + /** + * Get the range coverages corresponding to the tree. + * + * The ranges are pre-order sorted. + */ + toRanges() { + const ranges = []; + // Stack of parent trees and counts. + const stack = [[this, 0]]; + while (stack.length > 0) { + const [cur, parentCount] = stack.pop(); + const count = parentCount + cur.delta; + ranges.push({ + startOffset: cur.start, endOffset: cur.end, count + }); + for (let i = cur.children.length - 1; i >= 0; i--) { + stack.push([cur.children[i], count]); + } + } + return ranges; + } +} + +module.exports = RangeTree; diff --git a/node_modules/monocart-coverage-reports/lib/utils/request.js b/node_modules/monocart-coverage-reports/lib/utils/request.js new file mode 100644 index 0000000..2aca224 --- /dev/null +++ b/node_modules/monocart-coverage-reports/lib/utils/request.js @@ -0,0 +1,86 @@ +const http = require('http'); +const https = require('https'); + +// minimal http request for get sourcemap json +// https://nodejs.org/docs/latest/api/http.html#httprequesturl-options-callback +const request = (url, options) => { + + const HTTP = url.startsWith('https') ? https : http; + // console.log('request', url); + + return new Promise((resolve) => { + + // get method only + HTTP.get(url, options, (res) => { + const { statusCode } = res; + + // Any 2xx status code signals a successful response but here we're only checking for 200. + if (statusCode !== 200) { + // Consume response data to free up memory + res.resume(); + const resErr = new Error(`Request Failed. Status Code: ${statusCode}`); + resolve([resErr]); + return; + } + + res.setEncoding('utf8'); + + let rawData = ''; + res.on('data', (chunk) => { + rawData += chunk; + }); + + res.on('end', () => { + + let dataErr; + let data = rawData; + + // parse json + const contentType = res.headers['content-type']; + if ((/^application\/json/).test(contentType)) { + try { + data = JSON.parse(rawData); + } catch (e) { + dataErr = e; + } + } + + res.data = data; + resolve([dataErr, res]); + + }); + + }).on('error', (httpErr) => { + + resolve([httpErr]); + + }); + + }); +}; + +module.exports = async (url, options = {}) => { + let urlErr; + let urlObj; + try { + urlObj = new URL(url); + } catch (err) { + // console.error('error url', input); + urlErr = err; + } + + if (urlErr) { + return [urlErr]; + } + + const [err, res] = await request(urlObj.toString(), options); + if (err) { + // replace localhost to 127.0.0.1 + // ECONNREFUSED on NodeJS 18 https://github.com/node-fetch/node-fetch/issues/1624 + if (urlObj.hostname === 'localhost') { + urlObj.hostname = '127.0.0.1'; + return request(urlObj.toString(), options); + } + } + return [err, res]; +}; diff --git a/node_modules/monocart-coverage-reports/lib/utils/snapshot.js b/node_modules/monocart-coverage-reports/lib/utils/snapshot.js new file mode 100644 index 0000000..9b6df01 --- /dev/null +++ b/node_modules/monocart-coverage-reports/lib/utils/snapshot.js @@ -0,0 +1,348 @@ +const CG = require('console-grid'); +const EC = require('eight-colors'); + +const Util = require('./util.js'); + +const mergeSingleSubGroups = (item) => { + + if (!item.subs) { + return; + } + if (item.subs.length === 1) { + const sub = item.subs[0]; + if (!sub.subs) { + return; + } + item.name = [item.name, sub.name].filter((it) => it).join('/'); + item.subs = sub.subs; + mergeSingleSubGroups(item); + return; + } + + item.subs.forEach((sub) => { + mergeSingleSubGroups(sub); + }); + +}; + +const getGroupedRows = (flatRows) => { + let groups = []; + flatRows.forEach((file) => { + const pathList = file.name.split('/'); + const lastName = pathList.pop(); + let subs = groups; + pathList.forEach((key) => { + const item = subs.find((it) => it.name === key && it.subs); + if (item) { + subs = item.subs; + return; + } + const sub = { + name: key, + subs: [] + }; + subs.push(sub); + subs = sub.subs; + }); + + let filename = lastName; + if (file.nameStatus) { + filename = Util.getColorStrByStatus(lastName, file.nameStatus, 'ansicode'); + } + file.name = filename; + subs.push(file); + }); + const group = { + subs: groups + }; + mergeSingleSubGroups(group); + if (group.name) { + groups = [group]; + } + return groups; +}; + +// ============================================================ + +const diffUncoveredLines = (list) => { + const [oldStr, newStr] = list; + + const oldList = oldStr.split(','); + const newList = newStr.split(','); + + const oldColor = oldList.map((it) => { + if (newList.includes(it)) { + return it; + } + return EC.green(it); + }).join(','); + + const newColor = newList.map((it) => { + if (oldList.includes(it)) { + return it; + } + return EC.red(it); + }).join(','); + + return [oldColor, newColor]; +}; + +const getDiffMessage = (results, columns, diffOptions) => { + const flatRows = []; + results.forEach((it) => { + if (!it.change && diffOptions.skipEqual) { + return; + } + flatRows.push(it); + }); + + const rows = getGroupedRows(flatRows); + + const addedList = []; + Util.forEach(rows, (it, parent) => { + if (!it.change) { + return; + } + // add color + if (it.change === '-' || it.change === '+') { + columns.forEach((c) => { + const k = c.id; + let v = it[k]; + if (k === 'name') { + v = `${it.change} ${v}`; + } + it[k] = EC.red(v); + }); + return; + } + + // diff + const cloneRow = {}; + columns.forEach((c) => { + const k = c.id; + let v = it[k]; + if (Array.isArray(v)) { + if (k === 'uncoveredLines') { + v = diffUncoveredLines(v); + } else { + v = [EC.green(v[0]), EC.red(v[1])]; + } + it[k] = v[0]; + cloneRow[k] = v[1]; + return; + } + it[k] = v; + cloneRow[k] = ''; + }); + + addedList.push({ + subs: parent ? parent.subs : rows, + row: it, + cloneRow + }); + + }); + + addedList.forEach((it) => { + const { + subs, row, cloneRow + } = it; + const i = subs.findIndex((r) => r === row); + subs.splice(i + 1, 0, cloneRow); + }); + + // add innerBorder for summary + const summaryIndex = rows.findIndex((it) => it.isSummary); + if (summaryIndex !== -1) { + rows.splice(summaryIndex, 0, { + innerBorder: true + }); + } + + const lines = CG({ + options: { + silent: true, + nullPlaceholder: '', + defaultMaxWidth: diffOptions.maxCols + }, + columns, + rows + }); + + return lines.join('\n'); +}; + + +// ============================================================ + +const getSnapshot = (reportData) => { + const { + summary, files, type + } = reportData; + const snapshot = { + type, + summary: {}, + files: {} + }; + + const addPercent = (target, fromSummary) => { + Object.keys(fromSummary).forEach((k) => { + let percent = fromSummary[k].pct; + if (typeof percent === 'number') { + percent = Util.PSF(percent, 100, 2); + } + target[k] = percent; + }); + }; + + addPercent(snapshot.summary, summary); + + files.sort((a, b) => { + if (a.sourcePath > b.sourcePath) { + return 1; + } + return -1; + }); + files.forEach((file) => { + // do NOT add debug file + if (file.debug) { + return; + } + const fileSummary = {}; + addPercent(fileSummary, file.summary); + fileSummary.uncoveredLines = Util.getUncoveredLines(file.data.lines); + + // no extras for istanbul + const extras = file.data.extras; + fileSummary.extras = Object.keys(extras).map((k) => { + return k + extras[k]; + }).join(','); + + snapshot.files[file.sourcePath] = fileSummary; + }); + + return snapshot; +}; + +const diffSnapshot = (oldData, newData, diffOptions) => { + + diffOptions = { + skipEqual: true, + showSummary: true, + maxCols: 50, + metrics: [], + ... diffOptions + }; + + let change = false; + const results = []; + + const metrics = Util.getMetrics(diffOptions.metrics, oldData.type); + const columns = [{ + id: 'name', + name: 'Name' + }, ... metrics.map((m) => { + return { + id: m, + name: Util.capitalizeFirstLetter(m), + align: 'right' + }; + }), { + id: 'uncoveredLines', + name: 'Uncovered Lines' + }]; + + const keys = columns.map((it) => it.id).filter((it) => it !== 'name'); + const oFiles = oldData.files; + const nFiles = newData.files; + + Object.keys(oFiles).forEach((oPath) => { + + const oSummary = oFiles[oPath]; + + const diffResult = { + name: oPath + }; + keys.forEach((k) => { + diffResult[k] = oSummary[k]; + }); + + const nSummary = nFiles[oPath]; + if (nSummary) { + + let fileChange = false; + keys.forEach((k) => { + const oValue = oSummary[k]; + const nValue = nSummary[k]; + if (oValue !== nValue) { + change = true; + fileChange = true; + diffResult[k] = [oValue, nValue]; + } + }); + + diffResult.change = fileChange; + + } else { + change = true; + diffResult.change = '-'; + } + + results.push(diffResult); + + }); + + // added + Object.keys(nFiles).forEach((nPath) => { + const oSummary = oFiles[nPath]; + if (oSummary) { + return; + } + const nSummary = nFiles[nPath]; + const diffResult = { + name: nPath, + change: '+' + }; + change = true; + keys.forEach((k) => { + diffResult[k] = nSummary[k]; + }); + results.push(diffResult); + }); + + if (diffOptions.showSummary) { + const oSummary = oldData.summary; + const nSummary = newData.summary; + const diffResult = { + name: 'Summary', + isSummary: true, + change: false + }; + keys.forEach((k) => { + const oValue = oSummary[k]; + const nValue = nSummary[k]; + if (oValue === nValue) { + diffResult[k] = oValue; + } else { + change = true; + diffResult.change = true; + diffResult[k] = [oValue, nValue]; + } + }); + results.push(diffResult); + } + + const message = getDiffMessage(results, columns, diffOptions); + + return { + change, + results, + message + }; +}; + +module.exports = { + getGroupedRows, + getSnapshot, + diffSnapshot +}; diff --git a/node_modules/monocart-coverage-reports/lib/utils/source-path.js b/node_modules/monocart-coverage-reports/lib/utils/source-path.js new file mode 100644 index 0000000..2164039 --- /dev/null +++ b/node_modules/monocart-coverage-reports/lib/utils/source-path.js @@ -0,0 +1,251 @@ +const fs = require('fs'); +const path = require('path'); +const { fileURLToPath, pathToFileURL } = require('url'); +const Util = require('./util.js'); + +const resolveSourceRootUrl = (sourceName, sourceRoot) => { + // prepend sourceRoot + if (sourceRoot && !sourceName.startsWith(sourceRoot)) { + if (!sourceRoot.endsWith('/')) { + sourceRoot += '/'; + } + return sourceRoot + sourceName; + } + return sourceName; +}; + +const resolveAnonymousUrl = (url, index, type) => { + if (url) { + return url; + } + // anonymous scripts will have __playwright_evaluation_script__ as their URL. + const list = ['anonymous']; + if (index) { + list.push(`-${index}`); + } + if (type) { + list.push(`.${type}`); + } + return list.join(''); +}; + +const normalizePathDir = (sourcePath) => { + + // decodeURI("%20") to space + let str = decodeURI(`${sourcePath}`); + str = str.replace(/\\/g, '/'); + + // remove / of start, end or double, ./ ../ + return str.split('/').map((it) => { + it = it.trim(); + // remove illegal characters except / + it = it.replace(/[\\:*?"<>|]/g, ''); + // keep space + // it = it.replace(/\s+/g, '-'); + return it; + }).filter((item) => { + if (!item || item === '.' || item === '..') { + return false; + } + return true; + }).join('/'); +}; + +const betterFileURLToPath = (url) => { + try { + url = fileURLToPath(url); + } catch (e) { + url = decodeURIComponent(url); + url = fileURLToPath(url); + } + return url; +}; + +const normalizeSourcePath = (sourceUrl, baseDir) => { + + // includes anonymous and everything + + // file url + if (sourceUrl.startsWith('file:')) { + const relPath = Util.relativePath(betterFileURLToPath(sourceUrl), baseDir); + return normalizePathDir(relPath); + } + + // absolute path + // c:\\workspace\test\\selenium.spec.js true + // c://a.js true + // c:\\a.js true + // C:/a.js true + // /a.js true + + // a.js false + // ws://a.js false + // file://a.js false + // http://a.com/a.js false + // webpack://src/a.js false + + if (path.isAbsolute(sourceUrl)) { + const relPath = Util.relativePath(sourceUrl, baseDir); + return normalizePathDir(relPath); + } + + // ws://a.js + // http://127.0.0:8080/a.js + // https://127.0.0:8080/a.js?v=1 + // webpack://coverage-v8/./test/mock/src/branch/branch.js + // webpack://monocart-v8/../starfall-cli/node_modules/css-loader/dist/runtime/api.js + + // url http/https/webpack + const urlObj = Util.resolveUrl(sourceUrl); + if (urlObj) { + let host = urlObj.host; + // remove : before port, : can not be a part of dir + host = host.replace(':', '-'); + + // always start with '/' + const pathname = urlObj.pathname; + + let p = host + pathname; + // webpack://monocart-v8/packages/v8/src/app.vue?5cc4 + if (urlObj.search) { + p += `-${urlObj.search}`; + } + + return normalizePathDir(p); + } + + // relative path + const fileUrl = pathToFileURL(sourceUrl).toString(); + const relPath = Util.relativePath(betterFileURLToPath(fileUrl), baseDir); + return normalizePathDir(relPath); +}; + +const getSourceType = (sourcePath) => { + let ext = path.extname(sourcePath); + let type = 'js'; + if (ext) { + ext = ext.slice(1); + const reg = /^[a-z0-9]+$/; + if (reg.test(ext)) { + type = ext; + } + } + return type; +}; + + +// ======================================================================================================== + +const getSourcePathReplacer = (options) => { + const input = options.sourcePath; + if (typeof input === 'function') { + return input; + } + // object replace key with value + if (input && typeof input === 'object') { + const keys = Object.keys(input).filter((k) => typeof input[k] === 'string'); + if (keys.length) { + return (filePath) => { + keys.forEach((k) => { + filePath = filePath.replace(k, input[k]); + }); + return filePath; + }; + } + } +}; + +// ======================================================================================================== + +const initIstanbulSourcePath = (coverageData, fileSources, options) => { + + const sourcePathReplacer = getSourcePathReplacer(options); + + const newCoverage = {}; + // eslint-disable-next-line complexity + Object.keys(coverageData).forEach((sourcePath) => { + // previous coverage and source + const item = coverageData[sourcePath]; + let source = fileSources[sourcePath]; + + // source could be empty string '' + if (typeof source !== 'string') { + // read source with original source path first + source = Util.readFileSync(sourcePath); + if (typeof source === 'string') { + fileSources[sourcePath] = source; + } + } + + if (!fs.existsSync(sourcePath)) { + sourcePath = normalizePathDir(sourcePath); + } + + // new source path, second is source url + if (sourcePathReplacer) { + const newSourcePath = sourcePathReplacer(sourcePath, item); + if (typeof newSourcePath === 'string' && newSourcePath) { + sourcePath = newSourcePath; + } + } + + // update source path + if (item.data) { + item.data.path = sourcePath; + } else { + // from v8 + item.path = sourcePath; + } + + newCoverage[sourcePath] = item; + // update source for the new path + if (typeof source === 'string') { + fileSources[sourcePath] = source; + } + }); + + // console.log(Object.keys(fileSources)); + // console.log(newCoverage); + + return newCoverage; +}; + +// ======================================================================================================== + +const initSourceMapSourcesPath = (fileUrls, sourceMap, distFile, options) => { + + const baseDir = options.baseDir; + const sourcePathReplacer = getSourcePathReplacer(options); + + sourceMap.sources = sourceMap.sources.map((sourceName, i) => { + + let sourceUrl = resolveSourceRootUrl(sourceName, sourceMap.sourceRoot); + sourceUrl = resolveAnonymousUrl(sourceUrl, i + 1, 'js'); + let sourcePath = normalizeSourcePath(sourceUrl, baseDir); + // console.log(sourceUrl, sourcePath); + + if (sourcePathReplacer) { + // sourcePath could be a filename only, may using distFile to get full path + const newSourcePath = sourcePathReplacer(sourcePath, { + url: sourceUrl, + distFile + }); + if (typeof newSourcePath === 'string' && newSourcePath) { + sourcePath = newSourcePath; + } + } + + fileUrls[sourcePath] = sourceUrl; + return sourcePath; + }); + +}; + +module.exports = { + resolveAnonymousUrl, + normalizeSourcePath, + getSourceType, + getSourcePathReplacer, + initIstanbulSourcePath, + initSourceMapSourcesPath +}; diff --git a/node_modules/monocart-coverage-reports/lib/utils/util.js b/node_modules/monocart-coverage-reports/lib/utils/util.js new file mode 100644 index 0000000..08f75b6 --- /dev/null +++ b/node_modules/monocart-coverage-reports/lib/utils/util.js @@ -0,0 +1,963 @@ +const fs = require('fs'); +const { writeFile, readFile } = require('fs/promises'); +const path = require('path'); +const os = require('os'); +const crypto = require('crypto'); + +const EC = require('eight-colors'); +const CG = require('console-grid'); +const acornWalk = require('acorn-walk'); + +const Share = require('../platform/share.js'); +const request = require('./request.js'); +const version = require('../../package.json').version; +const markdownGrid = require('./markdown.js'); +const { mergeV8Coverage } = require('./merge/merge.js'); +const gc = require('./gc.js'); + +const { + findUpSync, supportsColor, minimatch +} = require('../packages/monocart-coverage-vendor.js'); + +// https://github.com/chalk/supports-color +// disabled color if Terminal stdout does not support color +if (!supportsColor.stdout) { + EC.disabled = true; +} + +const Util = { + version, + + ... Share, + + EC, + CG, + + root: process.cwd(), + + request, + markdownGrid, + mergeV8Coverage, + + forceGC: () => { + gc(); + }, + + relativePath: function(p, root) { + p = `${p}`; + root = `${root || Util.root}`; + let rp = path.relative(root, p); + rp = Util.formatPath(rp); + return rp; + }, + + replace: function(str, obj, defaultValue) { + str = `${str}`; + if (!obj) { + return str; + } + str = str.replace(/\{([^}{]+)\}/g, function(match, key) { + if (!Util.hasOwn(obj, key)) { + if (typeof (defaultValue) !== 'undefined') { + return defaultValue; + } + return match; + } + let val = obj[key]; + if (typeof (val) === 'function') { + val = val(obj, key); + } + if (typeof (val) === 'undefined') { + val = ''; + } + return val; + }); + return str; + }, + + strToObj: (str) => { + if (typeof str === 'string') { + str = str.trim(); + if (str.startsWith('{') && str.endsWith('}')) { + let fun; + let err; + try { + fun = new Function(`return ${str}`); + } catch (e) { + err = e; + } + if (!err) { + const obj = fun(); + if (obj && typeof obj === 'object') { + return obj; + } + } + } + } + }, + + calculateSha1: (buffer) => { + const hash = crypto.createHash('sha1'); + hash.update(buffer); + return hash.digest('hex'); + }, + + checkCoverageData: (data) => { + if (!data) { + return false; + } + if (Array.isArray(data) && data.length) { + return true; + } + if (Object.keys(data).length) { + return true; + } + return false; + }, + + resolveUrl: (input, base) => { + let url; + let err; + try { + url = new URL(input, base); + } catch (e) { + err = e; + } + if (err) { + // console.error('error url', input); + return; + } + return url; + }, + + resolveWatermarks: (defaultWatermarks, watermarks) => { + if (watermarks) { + if (Array.isArray(watermarks)) { + Object.keys(defaultWatermarks).forEach((k) => { + defaultWatermarks[k] = watermarks; + }); + } else { + Object.assign(defaultWatermarks, watermarks); + } + } + return defaultWatermarks; + }, + + resolveReportPath: (options, htmlPathHandler) => { + + let reportPath = options.reportPath; + if (typeof reportPath === 'function') { + reportPath = reportPath(); + } + + if (typeof reportPath === 'string') { + if (reportPath) { + const p = path.resolve(options.outputDir, reportPath); + return Util.relativePath(p); + } + // empty + return reportPath; + } + // using default html path as report path + return htmlPathHandler(); + }, + + getCacheFileInfo: (type, id, cacheDir) => { + const cacheName = `${type}-${id}.json`; + const cachePath = path.resolve(cacheDir, cacheName); + return { + cacheName, + cachePath + }; + }, + + betterMinimatch: (str, pattern) => { + str = `${str}`; + pattern = `${pattern}`; + + if (pattern === '*') { + return true; + } + + // includes first + if (str.includes(pattern)) { + return true; + } + + // with minimatch + if (minimatch(str, pattern)) { + return true; + } + + // after decode url + str = decodeURIComponent(str); + + if (str.includes(pattern)) { + return true; + } + + if (minimatch(str, pattern)) { + return true; + } + + return false; + }, + + // eslint-disable-next-line complexity + getEntryFilter: (options) => { + // for entry.url + + if (options.entryFilterHandler) { + return options.entryFilterHandler; + } + + let input = options.entryFilter || options.filter; + + // for function handler + if (typeof input === 'function') { + options.entryFilterHandler = input; + return input; + } + + // for single minimatch pattern + if (input && typeof input === 'string') { + // string to multiple patterns "{...}" + // mcr npx mocha --entryFilter {'**/node_modules/**':false,'**/src/*.js':true} + // mcr npx mocha --entryFilter "{'**/node_modules/**': false, '**/src/*.js': true}" + const obj = Util.strToObj(input); + if (obj) { + input = obj; + } else { + const handler = (entry) => { + return Util.betterMinimatch(entry.url, input); + }; + options.entryFilterHandler = handler; + return handler; + } + } + + // for patterns + if (input && typeof input === 'object') { + const patterns = Object.keys(input); + const handler = (entry) => { + const url = entry.url; + for (const pattern of patterns) { + if (Util.betterMinimatch(url, pattern)) { + return input[pattern]; + } + } + // false if not matched + }; + options.entryFilterHandler = handler; + return handler; + } + + // default + const handler = () => true; + options.entryFilterHandler = handler; + return handler; + }, + + // eslint-disable-next-line complexity + getSourceFilter: (options) => { + // for sourcePath + + if (options.sourceFilterHandler) { + return options.sourceFilterHandler; + } + + let input = options.sourceFilter || options.filter; + + // for function handler + if (typeof input === 'function') { + options.sourceFilterHandler = input; + return input; + } + + // for single minimatch pattern + if (input && typeof input === 'string') { + // string to multiple patterns "{...}" + // mcr npx mocha --sourceFilter {'**/node_modules/**':false,'**/src/*.js':true} + // mcr npx mocha --sourceFilter "{'**/node_modules/**': false, '**/src/*.js': true}" + const obj = Util.strToObj(input); + if (obj) { + input = obj; + } else { + const handler = (sourcePath) => { + return Util.betterMinimatch(sourcePath, input); + }; + options.sourceFilterHandler = handler; + return handler; + } + } + + // for patterns + if (input && typeof input === 'object') { + const patterns = Object.keys(input); + const handler = (sourcePath) => { + for (const pattern of patterns) { + if (Util.betterMinimatch(sourcePath, pattern)) { + return input[pattern]; + } + } + // false if not matched + }; + options.sourceFilterHandler = handler; + return handler; + } + + // default + const handler = () => true; + options.sourceFilterHandler = handler; + return handler; + }, + + setEmptyV8Coverage: (entry) => { + if (entry.type === 'css') { + // empty css + if (!entry.ranges) { + entry.ranges = []; + } + } else { + // empty js + if (!entry.functions) { + entry.functions = [{ + functionName: '', + ranges: [{ + startOffset: 0, + endOffset: entry.source ? entry.source.length : 0, + count: 0 + }] + }]; + } + } + }, + + saveSourceCacheFile: async (sourceData, options, fileCache) => { + const { cacheName, cachePath } = Util.getCacheFileInfo('source', sourceData.id, options.cacheDir); + + // file cache for add() to generate() + if (fileCache) { + fileCache.set(cacheName, sourceData); + } + + await Util.writeFile(cachePath, JSON.stringify(sourceData)); + + // save source and sourcemap file for debug + // https://evanw.github.io/source-map-visualization + if (options.sourceMap && sourceData.sourceMap) { + const filePath = cachePath.slice(0, -5); + await Util.writeFile(`${filePath}.js`, sourceData.source); + await Util.writeFile(`${filePath}.js.map`, JSON.stringify(sourceData.sourceMap)); + } + }, + + findUpConfig: (customConfigFile) => { + if (customConfigFile) { + if (fs.existsSync(customConfigFile)) { + return customConfigFile; + } + // custom config not found + return; + } + + const defaultConfigList = [ + 'mcr.config.js', + 'mcr.config.cjs', + 'mcr.config.mjs', + 'mcr.config.json', + 'mcr.config.ts' + ]; + + const configPath = findUpSync(defaultConfigList); + if (configPath) { + return configPath; + } + + // default config not found + }, + + getEOL: function(content) { + if (!content) { + return os.EOL; + } + const nIndex = content.lastIndexOf('\n'); + if (nIndex === -1) { + return os.EOL; + } + if (content.substr(nIndex - 1, 1) === '\r') { + return '\r\n'; + } + return '\n'; + }, + + visitAst: (rootNode, visitors) => { + const baseVisitor = acornWalk.base; + const parents = [rootNode]; + const visitor = (node, st, override) => { + const type = override || node.type; + // console.log('visit', node.type, override, parents.length); + const handler = visitors[type]; + if (handler) { + const res = handler(node, parents); + if (res === 'break') { + return; + } + } + const isNew = node !== parents[parents.length - 1]; + if (isNew) { + parents.push(node); + } + baseVisitor[type](node, st, visitor); + if (isNew) { + parents.pop(); + } + }; + visitor(rootNode); + }, + + updateOffsetToLocation: (locator, loc) => { + const sLoc = locator.offsetToLocation(loc.start); + loc.start = { + line: sLoc.line, + column: sLoc.column + }; + const eLoc = locator.offsetToLocation(loc.end); + loc.end = { + line: eLoc.line, + column: eLoc.column + }; + }, + + // offset key + sortOffsetRanges: (ranges) => { + ranges.sort((a, b) => { + if (a.startOffset === b.startOffset) { + return a.endOffset - b.endOffset; + } + return a.startOffset - b.startOffset; + }); + }, + + + forEachFile: function(dir, extList, callback) { + if (!fs.existsSync(dir)) { + return; + } + // all exts, full name, ext + const isMatched = (name) => !Util.isList(extList) || extList.includes(name) || extList.includes(path.extname(name)); + const subDirs = []; + const subDirHandler = () => { + if (!subDirs.length) { + return; + } + + for (const subDir of subDirs) { + const res = Util.forEachFile(subDir, extList, callback); + if (res === 'break') { + return; + } + } + }; + + const list = fs.readdirSync(dir); + for (const name of list) { + const abs = path.resolve(dir, name); + + const info = fs.lstatSync(abs); + if (info.isSymbolicLink()) { + continue; + } + + if (info.isDirectory()) { + subDirs.push(abs); + continue; + } + + if (info.isFile() && isMatched(name)) { + const res = callback(name, dir); + if (res === 'break') { + return; + } + } + + } + + subDirHandler(); + + }, + + readFileSync: function(filePath) { + if (fs.existsSync(filePath)) { + let buf; + try { + // Returns: | + buf = fs.readFileSync(filePath); + if (Buffer.isBuffer(buf)) { + return buf.toString('utf8'); + } + } catch (e) { + // ignore + } + return buf; + } + }, + + readFile: async (filePath) => { + if (fs.existsSync(filePath)) { + const buf = await readFile(filePath).catch((e) => { + Util.logError(`read file: ${filePath} ${e.message || e}`); + }); + if (Buffer.isBuffer(buf)) { + return buf.toString('utf8'); + } + return buf; + } + }, + + readJson: async (jsonPath) => { + const content = await Util.readFile(jsonPath); + if (content) { + return JSON.parse(content); + } + }, + + writeFileSync: function(filePath, content) { + if (!fs.existsSync(filePath)) { + const p = path.dirname(filePath); + if (!fs.existsSync(p)) { + fs.mkdirSync(p, { + recursive: true + }); + } + } + fs.writeFileSync(filePath, content); + }, + + writeFile: async (filePath, content) => { + if (!fs.existsSync(filePath)) { + const p = path.dirname(filePath); + if (!fs.existsSync(p)) { + fs.mkdirSync(p, { + recursive: true + }); + } + } + await writeFile(filePath, content).catch((e) => { + Util.logError(`write file: ${filePath} ${e.message || e}`); + }); + }, + + rmSync: (p) => { + if (!fs.existsSync(p)) { + return; + } + try { + fs.rmSync(p, { + recursive: true, + force: true, + maxRetries: 10 + }); + } catch (err) { + console.log(err.message); + } + }, + + normalizeColorType: (color) => { + return `${color}`.trim().toLowerCase(); + }, + + normalizeMaxCols: (maxCols, min = 1) => { + if (Util.isNum(maxCols)) { + return Math.max(maxCols, min); + } + }, + + getColorStrByStatus: (str, status, color = '') => { + + const colorHandlers = { + 'ansicode': () => { + if (status === 'low') { + return EC.red(str); + } + if (status === 'medium') { + return EC.yellow(str); + } + if (status === 'high') { + return EC.green(str); + } + return str; + }, + 'unicode': () => { + if (status === 'low') { + return `🔴 ${str}`; + } + if (status === 'medium') { + return `🟡 ${str}`; + } + if (status === 'high') { + return `🟢 ${str}`; + } + return str; + }, + 'html': () => { + if (status === 'low') { + return `${str}`; + } + if (status === 'medium') { + return `${str}`; + } + if (status === 'high') { + return `${str}`; + } + return str; + }, + 'tex': () => { + const texStr = str.replace(/%/g, '\\\\%'); + if (status === 'low') { + return `$\\color{red}{\\textsf{${texStr}}}$`; + } + if (status === 'medium') { + return `$\\color{orange}{\\textsf{${texStr}}}$`; + } + if (status === 'high') { + return `$\\color{green}{\\textsf{${texStr}}}$`; + } + return str; + } + }; + + const handler = colorHandlers[color]; + if (handler) { + return handler(); + } + // no color + return str; + }, + + getUncoveredLines: (dataLines, color = '') => { + + const lines = []; + + let startLine; + let endLine; + + const getHtmlColor = (c) => { + return c === 'yellow' ? 'orange' : c; + }; + + const getAnsiLink = () => { + if (startLine.value !== 'red' && endLine.value !== 'red' && endLine.line - startLine.line === 1) { + return EC.yellow('-'); + } + return EC.red('-'); + }; + + const getHtmlLink = () => { + if (startLine.value !== 'red' && endLine.value !== 'red' && endLine.line - startLine.line === 1) { + return '-'; + } + return '-'; + }; + + const addRangeItem = () => { + if (color === 'ansicode') { + lines.push(EC[startLine.value](startLine.line) + getAnsiLink() + EC[endLine.value](endLine.line)); + return; + } + + if (color === 'html') { + lines.push(`${startLine.line}${getHtmlLink()}${endLine.line}`); + return; + } + + // no color + lines.push(`${startLine.line}-${endLine.line}`); + + }; + + const addStartItem = () => { + if (color === 'ansicode') { + lines.push(EC[startLine.value](startLine.line)); + return; + } + + if (color === 'html') { + lines.push(`${startLine.line}`); + return; + } + + // no color + lines.push(startLine.line); + + }; + + const addLines = () => { + if (!startLine) { + return; + } + if (endLine) { + // range + addRangeItem(); + startLine = null; + endLine = null; + } else { + // only start + addStartItem(); + startLine = null; + } + }; + + const setLines = (line, value) => { + if (startLine) { + endLine = { + line, + value + }; + return; + } + startLine = { + line, + value + }; + }; + + Object.keys(dataLines).forEach((line) => { + const count = dataLines[line]; + if (count === 0) { + setLines(line, 'red'); + return; + } + // 0 < count < 1 + if (typeof count === 'string') { + setLines(line, 'yellow'); + return; + } + // count >= 1 + addLines(); + }); + addLines(); + + return lines.join(','); + }, + + // skip \s and comments + fixSourceRange: (locator, start, end) => { + + let fixedStart = start; + let fixedEnd = end; + + const rangeText = locator.getSlice(start, end); + + let text = rangeText; + + // ======================================= + // handle end first + const oldLen = text.length; + text = text.trimEnd(); + const newLen = text.length; + if (newLen < oldLen) { + fixedEnd -= oldLen - newLen; + } + + // ======================================= + // handle start + + const comments = locator.lineParser.commentParser.comments; + + let startOffset = 0; + + // never start in a comment, skip to comment end + const inComment = comments.find((it) => start > it.start && start < it.end); + if (inComment) { + startOffset = inComment.end - start; + // next text + text = text.slice(startOffset); + } + + while (startOffset < newLen) { + + const beforeLen = text.length; + text = text.trimStart(); + const afterLen = text.length; + if (afterLen === beforeLen) { + // no indent + break; + } + + const indentLen = beforeLen - afterLen; + + startOffset += indentLen; + + // no comments + if (!comments.length) { + break; + } + + const nextPos = start + startOffset; + const comment = comments.find((it) => it.start === nextPos); + if (!comment) { + break; + } + + const commentLen = comment.end - comment.start; + + startOffset += commentLen; + + // next text + text = text.slice(commentLen); + + } + + // It should never be possible to start with } + if (rangeText[startOffset] === '}') { + startOffset += 1; + } + + fixedStart = start + startOffset; + + return { + fixedStart, + fixedEnd + }; + }, + + cmpVersion: (v1, v2) => { + const [strMajor1, strMinor1, strPatch1] = `${v1}`.split('.'); + const [strMajor2, strMinor2, strPatch2] = `${v2}`.split('.'); + const strList = [strMajor1, strMinor1, strPatch1, strMajor2, strMinor2, strPatch2]; + const list = strList.map((str) => Util.toNum(parseInt(str))); + const [major1, minor1, patch1, major2, minor2, patch2] = list; + if (major1 === major2) { + if (minor1 === minor2) { + return patch1 - patch2; + } + return minor1 - minor2; + } + return major1 - major2; + }, + + // ========================================================================================== + + loggingLevels: { + off: 0, + error: 10, + info: 20, + debug: 30 + }, + loggingLevel: 20, + + isDebug: () => { + return Util.loggingType === 'debug'; + }, + + initLoggingLevel: (level) => { + + const types = { + off: 'off', + error: 'error', + info: 'info', + debug: 'debug' + }; + + level = level || process.env.MCR_LOGGING; + + const type = types[level] || types.info; + Util.loggingType = type; + Util.loggingLevel = Util.loggingLevels[type]; + + // console.log('========================================='); + // console.log(from, Util.loggingType, Util.loggingLevel); + + return type; + }, + + logError: (message) => { + if (Util.loggingLevel < Util.loggingLevels.error) { + return; + } + EC.logRed(`[MCR] ${message}`); + }, + + logInfo: (message) => { + if (Util.loggingLevel < Util.loggingLevels.info) { + return; + } + console.log(`[MCR] ${message}`); + }, + + // grid is info level + logGrid: (gridData) => { + if (Util.loggingLevel < Util.loggingLevels.info) { + return; + } + CG(gridData); + }, + + logDebug: (message) => { + if (Util.loggingLevel < Util.loggingLevels.debug) { + return; + } + console.log(`[MCR] ${message}`); + }, + + logFilter: (message, lengthBefore, lengthAfter) => { + if (Util.loggingLevel < Util.loggingLevels.debug) { + return; + } + if (lengthAfter < lengthBefore) { + lengthBefore = EC.yellow(lengthBefore); + lengthAfter = EC.yellow(lengthAfter); + } + console.log(`[MCR] ${message} before ${lengthBefore} => after ${lengthAfter}`); + }, + + setGC: (threshold) => { + if (!Util.isNum(threshold)) { + threshold = 1024; + } + Util.gcThreshold = threshold; + }, + + getMemory: () => { + const { heapUsed } = process.memoryUsage(); + const memory = parseFloat((heapUsed / 1024 ** 2).toFixed(1)); + return memory; + }, + + // time is debug level, fix the log info, for checking snapshot + logTime: (message, time_start) => { + + // memory gc + let memory = Util.getMemory(); + if (Util.gcThreshold && Util.gcThreshold < memory) { + Util.forceGC(); + } + + if (Util.loggingLevel < Util.loggingLevels.debug && !process.env.MCR_LOG_TIME) { + return; + } + const duration = Date.now() - time_start; + const durationH = Util.TF(duration); + const ls = [`[MCR] ${message}`]; + + memory = Util.getMemory(); + ls.push(` (memory: ${memory}MB)`); + + // time + ls.push(' ('); + if (duration <= 100) { + ls.push(EC.green(durationH)); + } else if (duration < 500) { + ls.push(EC.yellow(durationH)); + } else { + ls.push(EC.red(durationH)); + } + ls.push(')'); + + console.log(ls.join('')); + } + +}; + +module.exports = Util; diff --git a/node_modules/monocart-coverage-reports/lib/v8/v8-summary.js b/node_modules/monocart-coverage-reports/lib/v8/v8-summary.js new file mode 100644 index 0000000..3c9a49d --- /dev/null +++ b/node_modules/monocart-coverage-reports/lib/v8/v8-summary.js @@ -0,0 +1,138 @@ +const Util = require('../utils/util.js'); + +// both css and js +const getV8SummaryBytes = (item) => { + const source = item.source; + const total = source.length; + + // for empty coverage + if (item.empty) { + return { + total, + covered: 0 + }; + } + + const uncoveredBytes = item.data.bytes.filter((range) => range.count === 0); + + let uncovered = 0; + + let endPos = 0; + uncoveredBytes.forEach((range) => { + if (range.ignored) { + return; + } + + const { start, end } = range; + + if (start > endPos) { + uncovered += end - start; + endPos = end; + return; + } + + if (end <= endPos) { + return; + } + + uncovered += end - endPos; + endPos = end; + + }); + + const covered = total - uncovered; + + // console.log(item) + + return { + total, + covered + }; +}; + +// calculate uncovered, pct, status +const calculatePctAndStatus = (item, watermarks) => { + Object.keys(item).forEach((k) => { + const indicateData = item[k]; + indicateData.uncovered = indicateData.total - indicateData.covered; + + let pct = ''; + let status = 'unknown'; + + if (indicateData.total) { + pct = Util.PNF(indicateData.covered, indicateData.total, 2); + status = Util.getStatus(pct, watermarks[k]); + } + + indicateData.pct = pct; + indicateData.status = status; + + }); +}; + +const getV8Summary = (v8list, watermarks) => { + + // get bytes summary + v8list.forEach((entry) => { + entry.summary.bytes = getV8SummaryBytes(entry); + }); + + // overall summary + const summary = { + bytes: { + total: 0, + covered: 0 + }, + statements: { + total: 0, + covered: 0 + }, + branches: { + total: 0, + covered: 0 + }, + functions: { + total: 0, + covered: 0 + }, + lines: { + total: 0, + covered: 0, + blank: 0, + comment: 0 + } + }; + + v8list.forEach((entry) => { + const entrySummary = entry.summary; + calculatePctAndStatus(entrySummary, watermarks); + + // do NOT add debug file + if (entry.debug) { + return; + } + + Object.keys(entrySummary).forEach((k) => { + const indicateData = entrySummary[k]; + if (!indicateData) { + return; + } + summary[k].total += indicateData.total; + summary[k].covered += indicateData.covered; + + if (k === 'lines') { + summary[k].blank += indicateData.blank; + summary[k].comment += indicateData.comment; + } + }); + }); + + // calculate overall summary + calculatePctAndStatus(summary, watermarks); + + return summary; +}; + +module.exports = { + getV8Summary +}; diff --git a/node_modules/monocart-coverage-reports/lib/v8/v8.js b/node_modules/monocart-coverage-reports/lib/v8/v8.js new file mode 100644 index 0000000..28afae0 --- /dev/null +++ b/node_modules/monocart-coverage-reports/lib/v8/v8.js @@ -0,0 +1,343 @@ +const EC = require('eight-colors'); +const Util = require('../utils/util.js'); +const { getV8Summary } = require('./v8-summary.js'); +const { dedupeFlatRanges } = require('../utils/dedupe.js'); +const { + resolveAnonymousUrl, normalizeSourcePath, getSourcePathReplacer +} = require('../utils/source-path.js'); +const { collectSourceMaps } = require('../converter/collect-source-maps.js'); + +const { v8Report } = require('../reports/v8.js'); +const { v8JsonReport } = require('../reports/v8-json.js'); +const { customReport } = require('../reports/custom.js'); + +const getWrapperSource = (offset, source) => { + // NO \n because it break line number in mappings + let startStr = ''; + if (offset >= 4) { + // fill comments + const spaces = ''.padEnd(offset - 4, '*'); + startStr = `/*${spaces}*/`; + } else { + // fill spaces (should no chance) + startStr += ''.padEnd(offset, ' '); + } + return startStr + source; +}; + +const initV8ListAndSourcemap = async (mcr, v8list) => { + + const { options, fileCache } = mcr; + + // entry filter + const entryFilter = Util.getEntryFilter(options); + + const lengthBefore = v8list.length; + v8list = v8list.filter(entryFilter); + const lengthAfter = v8list.length; + Util.logFilter('entry filter (add):', lengthBefore, lengthAfter); + + // filter no source or text + // init type and css source from text + // keep functions + v8list = v8list.filter((entry) => { + + // console.log(entry.url); + + if (typeof entry.source === 'string' && entry.functions) { + entry.type = 'js'; + return true; + } + if (typeof entry.text === 'string' && entry.ranges) { + entry.type = 'css'; + return true; + } + // allow empty coverage + if (entry.empty) { + if (!['js', 'css'].includes(entry.type)) { + entry.type = 'js'; + } + return true; + } + + // 404 css, text will be empty + Util.logDebug(EC.red(`Invalid source or coverage data: ${entry.url}`)); + // console.log(entry); + }); + + // onEntry hook + // after filter but before init, because id depends source and sourcePath + const onEntry = options.onEntry; + if (typeof onEntry === 'function') { + for (const entry of v8list) { + await onEntry(entry); + } + } + + const sourcePathReplacer = getSourcePathReplacer(options); + + const baseDir = options.baseDir; + + // init id, sourcePath + v8list = v8list.map((entry, i) => { + + // it could be a empty file + let source = `${entry.source || entry.text || ''}`; + + // fix source with script offset + let scriptOffset; + const offset = Util.toNum(entry.scriptOffset, true); + if (offset > 0) { + scriptOffset = offset; + source = getWrapperSource(offset, source); + } + + const data = { + url: entry.url, + type: entry.type, + source, + // script offset >= 0, for vm script + scriptOffset, + // Manually Resolve the Sourcemap + sourceMap: entry.sourceMap, + // fake source with `lineLengths` + fake: entry.fake, + // empty coverage + empty: entry.empty, + // match source if using empty coverage + distFile: entry.distFile + }; + + // coverage info + if (data.type === 'css') { + data.ranges = entry.ranges; + } else { + data.functions = entry.functions; + } + + // resolve source path + const sourceUrl = resolveAnonymousUrl(data.url, i + 1, data.type); + let sourcePath = normalizeSourcePath(sourceUrl, baseDir); + if (sourcePathReplacer) { + const newSourcePath = sourcePathReplacer(sourcePath, data); + if (typeof newSourcePath === 'string' && newSourcePath) { + sourcePath = newSourcePath; + } + } + data.sourcePath = sourcePath; + // console.log(data.url, sourcePath); + + // calculate source id + data.id = Util.calculateSha1(sourcePath + data.source); + + return data; + }); + + // collect sourcemap first + const time_start = Date.now(); + const { sourceList, sourcemapList } = await collectSourceMaps(v8list, options); + if (sourcemapList.length) { + // debug level time + Util.logTime(`loaded sourcemaps: ${sourcemapList.length}`, time_start); + // console.log(smList); + } + + // save source list + for (const sourceData of sourceList) { + await Util.saveSourceCacheFile(sourceData, options, fileCache); + } + + return v8list; +}; + +// ======================================================================================================== + +// force to async +const mergeCssRanges = (itemList) => { + return new Promise((resolve) => { + + let concatRanges = []; + itemList.forEach((item) => { + concatRanges = concatRanges.concat(item.ranges); + }); + + // ranges: [ {start, end} ] + const ranges = dedupeFlatRanges(concatRanges); + + resolve(ranges); + }); +}; + +const mergeJsFunctions = async (itemList) => { + const res = await Util.mergeV8Coverage(itemList); + return res.functions; +}; + +const mergeV8DataList = async (dataList, options) => { + const allList = dataList.map((d) => d.data).flat(); + + // separate coverage and empty items + const coverageList = []; + const allEmptyList = []; + allList.forEach((it) => { + if (it.empty) { + allEmptyList.push(it); + } else { + coverageList.push(it); + } + }); + + // connect all functions and ranges + const itemMap = {}; + const sourcePathMap = {}; + const mergeMap = {}; + coverageList.forEach((item) => { + const { id, sourcePath } = item; + const prev = itemMap[id]; + if (prev) { + if (mergeMap[id]) { + mergeMap[id].push(item); + } else { + mergeMap[id] = [prev, item]; + } + } else { + itemMap[id] = item; + sourcePathMap[sourcePath] = item; + } + }); + + // merge functions and ranges + const mergeIds = Object.keys(mergeMap); + for (const id of mergeIds) { + const itemList = mergeMap[id]; + const item = itemMap[id]; + if (item.type === 'css') { + item.ranges = await mergeCssRanges(itemList); + } else { + item.functions = await mergeJsFunctions(itemList); + } + } + + // first time filter for empty, (not for sources) + // empty and not in item map + const emptyList = allEmptyList.filter((it) => { + if (itemMap[it.id]) { + return false; + } + if (sourcePathMap[it.sourcePath]) { + return false; + } + return true; + }); + + // merged list + empty list + const mergedList = Object.values(itemMap).concat(emptyList); + + return mergedList; +}; + +const mergeV8Coverage = async (dataList, sourceCache, options) => { + + const mergedList = await mergeV8DataList(dataList, options); + + // try to load coverage and source by id + for (const entry of mergedList) { + const json = sourceCache.get(entry.id); + if (json) { + entry.source = json.source; + entry.sourceMap = json.sourceMap; + } else { + Util.logError(`Not found source data: ${Util.relativePath(entry.sourcePath)}`); + entry.source = ''; + } + + // add empty coverage after source init + if (entry.empty) { + Util.setEmptyV8Coverage(entry); + } + + } + + // GC + sourceCache.clear(); + + return mergedList; +}; + +// ============================================================ + +const saveV8Report = async (v8list, options, istanbulReportPath) => { + + const defaultWatermarks = { + bytes: [50, 80], + statements: [50, 80], + branches: [50, 80], + functions: [50, 80], + lines: [50, 80] + }; + const watermarks = Util.resolveWatermarks(defaultWatermarks, options.watermarks); + + const summary = getV8Summary(v8list, watermarks); + + const reportData = { + type: 'v8', + // override with saved file path + reportPath: '', + version: Util.version, + name: options.name, + watermarks, + summary, + files: v8list + }; + + // v8 only reports + const buildInV8Reports = { + 'v8': v8Report, + 'v8-json': v8JsonReport + }; + + const outputs = {}; + const v8Group = options.reportGroup.get('v8'); + // could be no v8 only reports, but have `both` data reports + if (v8Group) { + for (const [reportName, reportOptions] of v8Group) { + const buildInHandler = buildInV8Reports[reportName]; + const t1 = Date.now(); + if (buildInHandler) { + outputs[reportName] = await buildInHandler(reportData, reportOptions, options); + } else { + outputs[reportName] = await customReport(reportName, reportData, reportOptions, options); + } + Util.logTime(`${EC.magenta('├')} [generate] saved report: ${reportName}`, t1); + } + } + + if (istanbulReportPath) { + outputs.istanbul = istanbulReportPath; + } + + // outputPath, should be html or json + const reportPath = Util.resolveReportPath(options, () => { + return outputs.v8 || outputs.istanbul || Object.values(outputs).filter((it) => it && typeof it === 'string').shift(); + }); + + const coverageResults = { + type: 'v8', + // html or json + reportPath, + version: Util.version, + name: options.name, + watermarks, + summary, + files: v8list + }; + + return coverageResults; +}; + +module.exports = { + initV8ListAndSourcemap, + mergeV8DataList, + mergeV8Coverage, + saveV8Report +}; diff --git a/node_modules/monocart-coverage-reports/package.json b/node_modules/monocart-coverage-reports/package.json new file mode 100644 index 0000000..9c4adfb --- /dev/null +++ b/node_modules/monocart-coverage-reports/package.json @@ -0,0 +1,133 @@ +{ + "name": "monocart-coverage-reports", + "version": "2.12.9", + "description": "A code coverage tool to generate native V8 reports or Istanbul reports.", + "main": "./lib/index.js", + "bin": { + "mcr": "./lib/cli.js" + }, + "exports": { + ".": { + "types": "./lib/index.d.ts", + "import": "./lib/index.mjs", + "require": "./lib/index.js" + }, + "./register": { + "import": "./lib/register/register.mjs", + "require": "./lib/register/register.js" + }, + "./converter": "./lib/converter/converter.js", + "./util": "./lib/utils/util.js", + "./package.json": "./package.json" + }, + "types": "./lib/index.d.ts", + "scripts": { + "build-test": "node ./test/build/build-test.js", + "build": "npx sf lint && npx sf b -p && npm run build-test", + "test-unit": "mocha --parallel test/unit/*.test.js", + "test-node-env": "cross-env NODE_V8_COVERAGE=.temp/v8-coverage-env node ./test/test-node-env.js && node ./test/generate-report.js", + "test-node-api": "cross-env NODE_V8_COVERAGE=.temp/v8-coverage-api node ./test/test-node-api.js", + "test-node-ins": "node ./test/test-node-ins.js", + "test-node-cdp": "node --inspect=9229 ./test/test-node-cdp.js", + "test-node-vm": "node ./test/test-node-vm.js", + "test-node-koa": "node ./test/test-node-koa.js", + "test-node-fgc": "node ./test/test-node-fgc.js", + "test-node": "node ./test/test.js --node", + "test-istanbul": "node ./test/test-istanbul.js", + "test-v8": "node ./test/test-v8.js", + "test-puppeteer": "node ./test/test-puppeteer.js", + "test-css": "node ./test/test-css.js", + "test-minify": "node ./test/test-minify.js", + "test-esbuild": "node ./test/test-esbuild.js", + "test-rollup": "node ./test/test-rollup.js", + "test-sections": "node ./test/test-sections.js", + "test-swc": "node ./test/test-swc.js", + "test-v8-and-istanbul": "node ./test/test-v8-and-istanbul.js", + "test-browser": "node ./test/test.js --browser", + "test-cli": "npx mcr node ./test/specs/node.test.js -c test/mcr.config.cli.js", + "test-demo": "node ./test/test-demo.js", + "test-merge": "node ./test/test-merge.js", + "test-merge-istanbul": "node ./test/test-merge-istanbul.js", + "test-merge-v8": "node ./test/test-merge-v8.js", + "test-merge-cli": "npx mcr merge -r console-details,v8 --inputDir .temp/code-coverage/raw --outputDir .temp/merge-cli", + "test-client": "node ./test/test-client.js", + "test-all": "node ./test/test.js", + "test-pr": "node --inspect=9230 ./test/test-pr.js", + "test": "npm run test-unit && npx mcr npm run test-all -c test/mcr.config.mcr.js && node ./scripts/docs.js", + "test:snap": "cross-env TEST_SNAPSHOT=true npm run test", + "dev": "npx sf d app", + "open": "node ./scripts/open.js", + "eol": "git rm -rf --cached . && git reset --hard HEAD", + "patch": "npm run build && npm run test && npx sf publish patch -r", + "beta": "npm version prerelease --preid=beta && npm run build && npm run test && npm publish --tag beta" + }, + "files": [ + "lib", + "README.zh-Hans.md" + ], + "license": "MIT", + "repository": { + "type": "git", + "url": "git+https://github.com/cenfun/monocart-coverage-reports.git" + }, + "dependencies": { + "acorn": "^8.15.0", + "acorn-loose": "^8.5.2", + "acorn-walk": "^8.3.4", + "commander": "^14.0.0", + "console-grid": "^2.2.3", + "eight-colors": "^1.3.1", + "foreground-child": "^3.3.1", + "istanbul-lib-coverage": "^3.2.2", + "istanbul-lib-report": "^3.0.1", + "istanbul-reports": "^3.2.0", + "lz-utils": "^2.1.0", + "monocart-locator": "^1.0.2" + }, + "devDependencies": { + "@actions/core": "^1.11.1", + "@actions/github": "^6.0.1", + "@jridgewell/sourcemap-codec": "^1.5.5", + "@jsdevtools/coverage-istanbul-loader": "^3.0.5", + "@rollup/plugin-commonjs": "^28.0.6", + "@rollup/plugin-typescript": "^12.1.4", + "async-tick": "^1.0.0", + "babel-loader": "^10.0.0", + "babel-plugin-istanbul": "^7.0.1", + "convert-source-map": "^2.0.0", + "cross-env": "^10.0.0", + "diff-sequences": "^29.6.3", + "esbuild": "^0.25.9", + "eslint": "~9.35.0", + "eslint-config-plus": "^2.0.3", + "eslint-plugin-html": "^8.1.3", + "eslint-plugin-vue": "^10.4.0", + "find-up": "^7.0.0", + "foreground-child": "^3.3.1", + "koa": "^3.0.1", + "koa-static-resolver": "^1.0.6", + "minimatch": "^9.0.5", + "mocha": "^11.7.2", + "monocart-code-viewer": "^1.1.5", + "monocart-formatter": "^3.0.1", + "node-stream-zip": "^1.15.0", + "open": "^10.2.0", + "playwright": "^1.55.0", + "postcss": "^8.5.6", + "puppeteer": "^24.19.0", + "rollup": "^4.50.1", + "starfall-cli": "^2.0.22", + "stylelint": "^16.24.0", + "stylelint-config-plus": "^1.1.4", + "supports-color": "^10.2.2", + "swc-loader": "^0.2.6", + "ts-loader": "^9.5.4", + "tsx": "^4.20.5", + "turbogrid": "^3.2.1", + "typescript": "^5.9.2", + "vine-ui": "^3.1.18", + "webpack": "^5.101.3", + "ws": "^8.18.3", + "yazl": "^3.3.1" + } +} diff --git a/node_modules/monocart-locator/LICENSE b/node_modules/monocart-locator/LICENSE new file mode 100644 index 0000000..6d8ec8b --- /dev/null +++ b/node_modules/monocart-locator/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2024 cenfun + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/node_modules/monocart-locator/README.md b/node_modules/monocart-locator/README.md new file mode 100644 index 0000000..da45af8 --- /dev/null +++ b/node_modules/monocart-locator/README.md @@ -0,0 +1,26 @@ +# Monocart Locator +[![](https://img.shields.io/npm/v/monocart-locator)](https://www.npmjs.com/package/monocart-locator) +[![](https://badgen.net/npm/dw/monocart-locator)](https://www.npmjs.com/package/monocart-locator) +![](https://img.shields.io/github/license/cenfun/monocart-locator) + +> A Locator for the source code position between offset and line/column. + +## Features +- Position locator +- Line parser +- Comment parser + +## Install +```sh +npm i monocart-locator +``` + +## Usage +```js +const locator = new Locator(source); +console.log(locator.lines); +console.log(locator.comments); + +const offset = locator.locationToOffset({ line: 1, column: 1 }); +const loc = locator.offsetToLocation(10); +``` \ No newline at end of file diff --git a/node_modules/monocart-locator/lib/comment-parser.js b/node_modules/monocart-locator/lib/comment-parser.js new file mode 100644 index 0000000..b92b1e8 --- /dev/null +++ b/node_modules/monocart-locator/lib/comment-parser.js @@ -0,0 +1,154 @@ +class CommentParser { + + // eslint-disable-next-line complexity + constructor(source) { + + const comments = []; + + let tokenClose = null; + + let isComment = false; + let block = false; + let start = 0; + + let closeOffset = 0; + let commentOffset = 0; + + let quote; + const quoteClose = (currentCharacter) => { + if (currentCharacter === '\\') { + closeOffset = 1; + return false; + } + closeOffset = 0; + return currentCharacter === quote; + }; + + const lineClose = (currentCharacter, nextCharacter) => { + if (currentCharacter === '\r' && nextCharacter === '\n') { + closeOffset = 1; + return true; + } + closeOffset = 0; + return currentCharacter === '\n'; + }; + + const blockClose = (currentCharacter, nextCharacter) => { + if (currentCharacter === '*' && nextCharacter === '/') { + closeOffset = 1; + commentOffset = 2; + return true; + } + closeOffset = 0; + return false; + }; + + const len = source.length; + for (let i = 0; i < len; i++) { + const currentCharacter = source[i]; + const nextCharacter = source[i + 1]; + + if (tokenClose !== null) { + if (tokenClose(currentCharacter, nextCharacter)) { + if (isComment) { + comments.push({ + block, + start, + end: i + commentOffset + }); + } + tokenClose = null; + } + i += closeOffset; + continue; + } + + // string singleQuote doubleQuote backQuote + if (currentCharacter === "'" || currentCharacter === '"' || currentCharacter === '`') { + quote = currentCharacter; + isComment = false; + tokenClose = quoteClose; + continue; + } + + // line comments + if (currentCharacter === '/' && nextCharacter === '/') { + block = false; + isComment = true; + commentOffset = 0; + start = i; + tokenClose = lineClose; + i += 1; + continue; + } + + // block comments + if (currentCharacter === '/' && nextCharacter === '*') { + block = true; + isComment = true; + commentOffset = 0; + start = i; + tokenClose = blockClose; + i += 1; + } + + } + + if (tokenClose && isComment) { + comments.push({ + block, + start, + end: len + }); + } + + // add comment text + comments.forEach((it) => { + it.text = source.slice(it.start, it.end); + }); + + this.comments = comments; + + } + + isComment(start, end) { + if (!this.comments.length) { + return false; + } + const comment = this.findComment(start); + if (start >= comment.start && end <= comment.end) { + return true; + } + return false; + } + + findComment(position) { + const list = this.comments; + let start = 0; + let end = list.length - 1; + while (end - start > 1) { + const i = Math.floor((start + end) * 0.5); + const item = list[i]; + if (position < item.start) { + end = i; + continue; + } + if (position > item.end) { + start = i; + continue; + } + return list[i]; + } + // last two items, less is start + const endItem = list[end]; + if (position < endItem.start) { + return list[start]; + } + return list[end]; + + } + + +} + +module.exports = CommentParser; diff --git a/node_modules/monocart-locator/lib/index.d.ts b/node_modules/monocart-locator/lib/index.d.ts new file mode 100644 index 0000000..56ddab2 --- /dev/null +++ b/node_modules/monocart-locator/lib/index.d.ts @@ -0,0 +1,61 @@ +export type CommentItem = { + block: boolean; + start: number; + end: number; + text: string; +} + +export class CommentParser { + constructor(source: string); + comments: CommentItem[]; + isComment(start: number, end: number): boolean; +} + + +export type LineItem = { + /** 0-base */ + line: number; + + length: number; + indent: number; + + start: number; + end: number; + + blank?: boolean; + comment?: boolean; + + text: string; +} + +export class LineParser { + constructor(source: string); + lines: LineItem[]; + comments: CommentItem[]; + findLine(pos: number): LineItem; +} + + +export type LocationItem = LineItem & { + /** 1-base */ + line: number; + column: number; +} + +export class Locator { + constructor(source: string); + source: string; + lineParser: LineParser; + lines: LineItem[]; + comments: CommentItem[]; + + /** 1-base */ + locationToOffset(loc: LocationItem): number; + offsetToLocation(offset: number): LocationItem; + + getSlice(start: number, end?: number): string; + + /** 1-base to 0-base */ + getLine(line: number): LineItem; + +} \ No newline at end of file diff --git a/node_modules/monocart-locator/lib/index.js b/node_modules/monocart-locator/lib/index.js new file mode 100644 index 0000000..2fe90ae --- /dev/null +++ b/node_modules/monocart-locator/lib/index.js @@ -0,0 +1,10 @@ +const Locator = require('./locator.js'); +const LineParser = require('./line-parser.js'); +const CommentParser = require('./comment-parser.js'); + +module.exports = { + Locator, + LineParser, + CommentParser +}; + diff --git a/node_modules/monocart-locator/lib/index.mjs b/node_modules/monocart-locator/lib/index.mjs new file mode 100644 index 0000000..7fe9917 --- /dev/null +++ b/node_modules/monocart-locator/lib/index.mjs @@ -0,0 +1,3 @@ +export * from './index.js'; +import locator from './index.js'; +export default locator; diff --git a/node_modules/monocart-locator/lib/line-parser.js b/node_modules/monocart-locator/lib/line-parser.js new file mode 100644 index 0000000..dfb95ff --- /dev/null +++ b/node_modules/monocart-locator/lib/line-parser.js @@ -0,0 +1,100 @@ +const CommentParser = require('./comment-parser.js'); + +class LineParser { + constructor(content = '') { + let pos = 0; + + // force to string + if (typeof content !== 'string') { + content = `${content}`; + } + + const commentParser = new CommentParser(content); + this.commentParser = commentParser; + this.comments = commentParser.comments; + + // only \n, common on Linux and macOS + // \r\n, common on Windows + this.lines = content.split(/\n/).map((text, line) => { + + let n = 1; + // may ends with \r + const reg = /\r$/; + if (reg.test(text)) { + text = text.slice(0, -1); + n += 1; + } + + const length = text.length; + const start = pos; + const end = start + length; + + pos += length + n; + + // ============================= + const blankBlock = /\S/; + + let blank = false; + if (!blankBlock.test(text)) { + blank = true; + } + + // ============================= + let comment = false; + let indent = length; + if (!blank) { + indent = text.search(blankBlock); + + if (commentParser.isComment(start + indent, end)) { + comment = true; + } + + } + + // ============================= + + return { + line, + + length, + indent, + + start, + end, + + blank, + comment, + + text + }; + }); + } + + findLine(position) { + const list = this.lines; + let start = 0; + let end = list.length - 1; + while (end - start > 1) { + const i = Math.floor((start + end) * 0.5); + const item = list[i]; + if (position < item.start) { + end = i; + continue; + } + if (position > item.end) { + start = i; + continue; + } + return list[i]; + } + // last two items, less is start + const endItem = list[end]; + if (position < endItem.start) { + return list[start]; + } + return list[end]; + } + +} + +module.exports = LineParser; diff --git a/node_modules/monocart-locator/lib/locator.js b/node_modules/monocart-locator/lib/locator.js new file mode 100644 index 0000000..84368d0 --- /dev/null +++ b/node_modules/monocart-locator/lib/locator.js @@ -0,0 +1,53 @@ +const LineParser = require('./line-parser.js'); +class Locator { + constructor(source) { + this.source = source; + this.lineParser = new LineParser(source); + this.lines = this.lineParser.lines; + this.comments = this.lineParser.comments; + } + + // 1-base + locationToOffset(location) { + const { line, column } = location; + // 1-based + const lineInfo = this.lines[line - 1]; + if (lineInfo) { + if (column === Infinity) { + return lineInfo.start + lineInfo.length; + } + return lineInfo.start + Math.min(column, lineInfo.length); + } + return 0; + } + + // 1-base + offsetToLocation(offset) { + const lineInfo = this.lineParser.findLine(offset); + + // 1-base + const line = lineInfo.line + 1; + + const column = Math.min(Math.max(offset - lineInfo.start, 0), lineInfo.length); + + return { + ... lineInfo, + line, + column + }; + } + + getSlice(s, e) { + return this.source.slice(s, e); + } + + // 1-base + getLine(line) { + return this.lines[line - 1]; + } + + +} + +module.exports = Locator; + diff --git a/node_modules/monocart-locator/package.json b/node_modules/monocart-locator/package.json new file mode 100644 index 0000000..893f17a --- /dev/null +++ b/node_modules/monocart-locator/package.json @@ -0,0 +1,32 @@ +{ + "name": "monocart-locator", + "version": "1.0.2", + "description": "Monocart Locator", + "main": "./lib/index.js", + "exports": { + ".": { + "types": "./lib/index.d.ts", + "import": "./lib/index.mjs", + "require": "./lib/index.js", + "default": "./lib/index.js" + }, + "./package.json": "./package.json" + }, + "types": "./lib/index.d.ts", + "scripts": { + "test": "mocha", + "patch": "npm run test && sf publish patch" + }, + "files": [ + "lib" + ], + "license": "MIT", + "dependencies": {}, + "devDependencies": { + "console-grid": "^2.2.2", + "eight-colors": "^1.3.0", + "eslint": "^9.6.0", + "eslint-config-plus": "^2.0.2", + "mocha": "^10.5.2" + } +} diff --git a/node_modules/path-key/index.d.ts b/node_modules/path-key/index.d.ts new file mode 100644 index 0000000..7c575d1 --- /dev/null +++ b/node_modules/path-key/index.d.ts @@ -0,0 +1,40 @@ +/// + +declare namespace pathKey { + interface Options { + /** + Use a custom environment variables object. Default: [`process.env`](https://nodejs.org/api/process.html#process_process_env). + */ + readonly env?: {[key: string]: string | undefined}; + + /** + Get the PATH key for a specific platform. Default: [`process.platform`](https://nodejs.org/api/process.html#process_process_platform). + */ + readonly platform?: NodeJS.Platform; + } +} + +declare const pathKey: { + /** + Get the [PATH](https://en.wikipedia.org/wiki/PATH_(variable)) environment variable key cross-platform. + + @example + ``` + import pathKey = require('path-key'); + + const key = pathKey(); + //=> 'PATH' + + const PATH = process.env[key]; + //=> '/usr/local/bin:/usr/bin:/bin' + ``` + */ + (options?: pathKey.Options): string; + + // TODO: Remove this for the next major release, refactor the whole definition to: + // declare function pathKey(options?: pathKey.Options): string; + // export = pathKey; + default: typeof pathKey; +}; + +export = pathKey; diff --git a/node_modules/path-key/index.js b/node_modules/path-key/index.js new file mode 100644 index 0000000..0cf6415 --- /dev/null +++ b/node_modules/path-key/index.js @@ -0,0 +1,16 @@ +'use strict'; + +const pathKey = (options = {}) => { + const environment = options.env || process.env; + const platform = options.platform || process.platform; + + if (platform !== 'win32') { + return 'PATH'; + } + + return Object.keys(environment).reverse().find(key => key.toUpperCase() === 'PATH') || 'Path'; +}; + +module.exports = pathKey; +// TODO: Remove this for the next major release +module.exports.default = pathKey; diff --git a/node_modules/path-key/license b/node_modules/path-key/license new file mode 100644 index 0000000..e7af2f7 --- /dev/null +++ b/node_modules/path-key/license @@ -0,0 +1,9 @@ +MIT License + +Copyright (c) Sindre Sorhus (sindresorhus.com) + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/node_modules/path-key/package.json b/node_modules/path-key/package.json new file mode 100644 index 0000000..c8cbd38 --- /dev/null +++ b/node_modules/path-key/package.json @@ -0,0 +1,39 @@ +{ + "name": "path-key", + "version": "3.1.1", + "description": "Get the PATH environment variable key cross-platform", + "license": "MIT", + "repository": "sindresorhus/path-key", + "author": { + "name": "Sindre Sorhus", + "email": "sindresorhus@gmail.com", + "url": "sindresorhus.com" + }, + "engines": { + "node": ">=8" + }, + "scripts": { + "test": "xo && ava && tsd" + }, + "files": [ + "index.js", + "index.d.ts" + ], + "keywords": [ + "path", + "key", + "environment", + "env", + "variable", + "var", + "get", + "cross-platform", + "windows" + ], + "devDependencies": { + "@types/node": "^11.13.0", + "ava": "^1.4.1", + "tsd": "^0.7.2", + "xo": "^0.24.0" + } +} diff --git a/node_modules/path-key/readme.md b/node_modules/path-key/readme.md new file mode 100644 index 0000000..a9052d7 --- /dev/null +++ b/node_modules/path-key/readme.md @@ -0,0 +1,61 @@ +# path-key [![Build Status](https://travis-ci.org/sindresorhus/path-key.svg?branch=master)](https://travis-ci.org/sindresorhus/path-key) + +> Get the [PATH](https://en.wikipedia.org/wiki/PATH_(variable)) environment variable key cross-platform + +It's usually `PATH`, but on Windows it can be any casing like `Path`... + + +## Install + +``` +$ npm install path-key +``` + + +## Usage + +```js +const pathKey = require('path-key'); + +const key = pathKey(); +//=> 'PATH' + +const PATH = process.env[key]; +//=> '/usr/local/bin:/usr/bin:/bin' +``` + + +## API + +### pathKey(options?) + +#### options + +Type: `object` + +##### env + +Type: `object`
+Default: [`process.env`](https://nodejs.org/api/process.html#process_process_env) + +Use a custom environment variables object. + +#### platform + +Type: `string`
+Default: [`process.platform`](https://nodejs.org/api/process.html#process_process_platform) + +Get the PATH key for a specific platform. + + +--- + +
+ + Get professional support for this package with a Tidelift subscription + +
+ + Tidelift helps make open source sustainable for maintainers while giving companies
assurances about security, maintenance, and licensing for their dependencies. +
+
diff --git a/node_modules/playwright-core/LICENSE b/node_modules/playwright-core/LICENSE new file mode 100644 index 0000000..4ace03d --- /dev/null +++ b/node_modules/playwright-core/LICENSE @@ -0,0 +1,202 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Portions Copyright (c) Microsoft Corporation. + Portions Copyright 2017 Google Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/node_modules/playwright-core/NOTICE b/node_modules/playwright-core/NOTICE new file mode 100644 index 0000000..814ec16 --- /dev/null +++ b/node_modules/playwright-core/NOTICE @@ -0,0 +1,5 @@ +Playwright +Copyright (c) Microsoft Corporation + +This software contains code derived from the Puppeteer project (https://github.com/puppeteer/puppeteer), +available under the Apache 2.0 license (https://github.com/puppeteer/puppeteer/blob/master/LICENSE). diff --git a/node_modules/playwright-core/README.md b/node_modules/playwright-core/README.md new file mode 100644 index 0000000..422b373 --- /dev/null +++ b/node_modules/playwright-core/README.md @@ -0,0 +1,3 @@ +# playwright-core + +This package contains the no-browser flavor of [Playwright](http://github.com/microsoft/playwright). diff --git a/node_modules/playwright-core/ThirdPartyNotices.txt b/node_modules/playwright-core/ThirdPartyNotices.txt new file mode 100644 index 0000000..369e202 --- /dev/null +++ b/node_modules/playwright-core/ThirdPartyNotices.txt @@ -0,0 +1,13 @@ +microsoft/playwright-core + +THIRD-PARTY SOFTWARE NOTICES AND INFORMATION + +This package bundles third-party software inside individual files under +`lib/`. Each bundled output has a sidecar `.js.LICENSE` file next +to it listing every npm package whose source was inlined into that +bundle, together with the full license text for each. + +For example: +- lib/utilsBundle.js.LICENSE + +This project incorporates components from the projects listed below. The original copyright notices and the licenses under which Microsoft received such components are set forth below. Microsoft reserves all rights not expressly granted herein, whether by implication, estoppel or otherwise. diff --git a/node_modules/playwright-core/bin/install_media_pack.ps1 b/node_modules/playwright-core/bin/install_media_pack.ps1 new file mode 100644 index 0000000..6170754 --- /dev/null +++ b/node_modules/playwright-core/bin/install_media_pack.ps1 @@ -0,0 +1,5 @@ +$osInfo = Get-WmiObject -Class Win32_OperatingSystem +# check if running on Windows Server +if ($osInfo.ProductType -eq 3) { + Install-WindowsFeature Server-Media-Foundation +} diff --git a/node_modules/playwright-core/bin/install_webkit_wsl.ps1 b/node_modules/playwright-core/bin/install_webkit_wsl.ps1 new file mode 100644 index 0000000..ccaaf15 --- /dev/null +++ b/node_modules/playwright-core/bin/install_webkit_wsl.ps1 @@ -0,0 +1,33 @@ +$ErrorActionPreference = 'Stop' + +# This script sets up a WSL distribution that will be used to run WebKit. + +$Distribution = "playwright" +$Username = "pwuser" + +$distributions = (wsl --list --quiet) -split "\r?\n" +if ($distributions -contains $Distribution) { + Write-Host "WSL distribution '$Distribution' already exists. Skipping installation." +} else { + Write-Host "Installing new WSL distribution '$Distribution'..." + $VhdSize = "10GB" + wsl --install -d Ubuntu-24.04 --name $Distribution --no-launch --vhd-size $VhdSize + wsl -d $Distribution -u root adduser --gecos GECOS --disabled-password $Username +} + +$pwshDirname = (Resolve-Path -Path $PSScriptRoot).Path; +$playwrightCoreRoot = Resolve-Path (Join-Path $pwshDirname "..") + +$initScript = @" +if [ ! -f "/home/$Username/node/bin/node" ]; then + mkdir -p /home/$Username/node + curl -fsSL https://nodejs.org/dist/v22.17.0/node-v22.17.0-linux-x64.tar.xz -o /home/$Username/node/node-v22.17.0-linux-x64.tar.xz + tar -xJf /home/$Username/node/node-v22.17.0-linux-x64.tar.xz -C /home/$Username/node --strip-components=1 + sudo -u $Username echo 'export PATH=/home/$Username/node/bin:\`$PATH' >> /home/$Username/.profile +fi +/home/$Username/node/bin/node cli.js install-deps webkit +sudo -u $Username PLAYWRIGHT_SKIP_BROWSER_GC=1 /home/$Username/node/bin/node cli.js install webkit +"@ -replace "\r\n", "`n" + +wsl -d $Distribution --cd $playwrightCoreRoot -u root -- bash -c "$initScript" +Write-Host "Done!" \ No newline at end of file diff --git a/node_modules/playwright-core/bin/reinstall_chrome_beta_linux.sh b/node_modules/playwright-core/bin/reinstall_chrome_beta_linux.sh new file mode 100644 index 0000000..13d55df --- /dev/null +++ b/node_modules/playwright-core/bin/reinstall_chrome_beta_linux.sh @@ -0,0 +1,42 @@ +#!/usr/bin/env bash +set -e +set -x + +if [[ $(arch) == "aarch64" ]]; then + echo "ERROR: not supported on Linux Arm64" + exit 1 +fi + +if [ -z "$PLAYWRIGHT_HOST_PLATFORM_OVERRIDE" ]; then + if [[ ! -f "/etc/os-release" ]]; then + echo "ERROR: cannot install on unknown linux distribution (/etc/os-release is missing)" + exit 1 + fi + + ID=$(bash -c 'source /etc/os-release && echo $ID') + if [[ "${ID}" != "ubuntu" && "${ID}" != "debian" ]]; then + echo "ERROR: cannot install on $ID distribution - only Ubuntu and Debian are supported" + exit 1 + fi +fi + +# 1. make sure to remove old beta if any. +if dpkg --get-selections | grep -q "^google-chrome-beta[[:space:]]*install$" >/dev/null; then + apt-get remove -y google-chrome-beta +fi + +# 2. Update apt lists (needed to install curl and chrome dependencies) +apt-get update + +# 3. Install curl to download chrome +if ! command -v curl >/dev/null; then + apt-get install -y curl +fi + +# 4. download chrome beta from dl.google.com and install it. +cd /tmp +curl -L -O https://dl.google.com/linux/direct/google-chrome-beta_current_amd64.deb +apt-get install -y ./google-chrome-beta_current_amd64.deb +rm -rf ./google-chrome-beta_current_amd64.deb +cd - +google-chrome-beta --version diff --git a/node_modules/playwright-core/bin/reinstall_chrome_beta_mac.sh b/node_modules/playwright-core/bin/reinstall_chrome_beta_mac.sh new file mode 100644 index 0000000..60b4b7f --- /dev/null +++ b/node_modules/playwright-core/bin/reinstall_chrome_beta_mac.sh @@ -0,0 +1,13 @@ +#!/usr/bin/env bash +set -e +set -x + +rm -rf "/Applications/Google Chrome Beta.app" +cd /tmp +curl -L --retry 3 -o ./googlechromebeta.dmg https://dl.google.com/chrome/mac/universal/beta/googlechromebeta.dmg +hdiutil attach -nobrowse -quiet -noautofsck -noautoopen -mountpoint /Volumes/googlechromebeta.dmg ./googlechromebeta.dmg +cp -pR "/Volumes/googlechromebeta.dmg/Google Chrome Beta.app" /Applications +hdiutil detach /Volumes/googlechromebeta.dmg +rm -rf /tmp/googlechromebeta.dmg + +/Applications/Google\ Chrome\ Beta.app/Contents/MacOS/Google\ Chrome\ Beta --version diff --git a/node_modules/playwright-core/bin/reinstall_chrome_beta_win.ps1 b/node_modules/playwright-core/bin/reinstall_chrome_beta_win.ps1 new file mode 100644 index 0000000..3fbe551 --- /dev/null +++ b/node_modules/playwright-core/bin/reinstall_chrome_beta_win.ps1 @@ -0,0 +1,24 @@ +$ErrorActionPreference = 'Stop' + +$url = 'https://dl.google.com/tag/s/dl/chrome/install/beta/googlechromebetastandaloneenterprise64.msi' + +Write-Host "Downloading Google Chrome Beta" +$wc = New-Object net.webclient +$msiInstaller = "$env:temp\google-chrome-beta.msi" +$wc.Downloadfile($url, $msiInstaller) + +Write-Host "Installing Google Chrome Beta" +$arguments = "/i `"$msiInstaller`" /quiet" +Start-Process msiexec.exe -ArgumentList $arguments -Wait +Remove-Item $msiInstaller + +$suffix = "\\Google\\Chrome Beta\\Application\\chrome.exe" +if (Test-Path "${env:ProgramFiles(x86)}$suffix") { + (Get-Item "${env:ProgramFiles(x86)}$suffix").VersionInfo +} elseif (Test-Path "${env:ProgramFiles}$suffix") { + (Get-Item "${env:ProgramFiles}$suffix").VersionInfo +} else { + Write-Host "ERROR: Failed to install Google Chrome Beta." + Write-Host "ERROR: This could be due to insufficient privileges, in which case re-running as Administrator may help." + exit 1 +} diff --git a/node_modules/playwright-core/bin/reinstall_chrome_stable_linux.sh b/node_modules/playwright-core/bin/reinstall_chrome_stable_linux.sh new file mode 100644 index 0000000..64bc139 --- /dev/null +++ b/node_modules/playwright-core/bin/reinstall_chrome_stable_linux.sh @@ -0,0 +1,42 @@ +#!/usr/bin/env bash +set -e +set -x + +if [[ $(arch) == "aarch64" ]]; then + echo "ERROR: not supported on Linux Arm64" + exit 1 +fi + +if [ -z "$PLAYWRIGHT_HOST_PLATFORM_OVERRIDE" ]; then + if [[ ! -f "/etc/os-release" ]]; then + echo "ERROR: cannot install on unknown linux distribution (/etc/os-release is missing)" + exit 1 + fi + + ID=$(bash -c 'source /etc/os-release && echo $ID') + if [[ "${ID}" != "ubuntu" && "${ID}" != "debian" ]]; then + echo "ERROR: cannot install on $ID distribution - only Ubuntu and Debian are supported" + exit 1 + fi +fi + +# 1. make sure to remove old stable if any. +if dpkg --get-selections | grep -q "^google-chrome[[:space:]]*install$" >/dev/null; then + apt-get remove -y google-chrome +fi + +# 2. Update apt lists (needed to install curl and chrome dependencies) +apt-get update + +# 3. Install curl to download chrome +if ! command -v curl >/dev/null; then + apt-get install -y curl +fi + +# 4. download chrome stable from dl.google.com and install it. +cd /tmp +curl -L -O https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb +apt-get install -y ./google-chrome-stable_current_amd64.deb +rm -rf ./google-chrome-stable_current_amd64.deb +cd - +google-chrome --version diff --git a/node_modules/playwright-core/bin/reinstall_chrome_stable_mac.sh b/node_modules/playwright-core/bin/reinstall_chrome_stable_mac.sh new file mode 100644 index 0000000..7db7a0f --- /dev/null +++ b/node_modules/playwright-core/bin/reinstall_chrome_stable_mac.sh @@ -0,0 +1,12 @@ +#!/usr/bin/env bash +set -e +set -x + +rm -rf "/Applications/Google Chrome.app" +cd /tmp +curl -L --retry 3 -o ./googlechrome.dmg https://dl.google.com/chrome/mac/universal/stable/GGRO/googlechrome.dmg +hdiutil attach -nobrowse -quiet -noautofsck -noautoopen -mountpoint /Volumes/googlechrome.dmg ./googlechrome.dmg +cp -pR "/Volumes/googlechrome.dmg/Google Chrome.app" /Applications +hdiutil detach /Volumes/googlechrome.dmg +rm -rf /tmp/googlechrome.dmg +/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome --version diff --git a/node_modules/playwright-core/bin/reinstall_chrome_stable_win.ps1 b/node_modules/playwright-core/bin/reinstall_chrome_stable_win.ps1 new file mode 100644 index 0000000..7ca2dba --- /dev/null +++ b/node_modules/playwright-core/bin/reinstall_chrome_stable_win.ps1 @@ -0,0 +1,24 @@ +$ErrorActionPreference = 'Stop' +$url = 'https://dl.google.com/tag/s/dl/chrome/install/googlechromestandaloneenterprise64.msi' + +$wc = New-Object net.webclient +$msiInstaller = "$env:temp\google-chrome.msi" +Write-Host "Downloading Google Chrome" +$wc.Downloadfile($url, $msiInstaller) + +Write-Host "Installing Google Chrome" +$arguments = "/i `"$msiInstaller`" /quiet" +Start-Process msiexec.exe -ArgumentList $arguments -Wait +Remove-Item $msiInstaller + + +$suffix = "\\Google\\Chrome\\Application\\chrome.exe" +if (Test-Path "${env:ProgramFiles(x86)}$suffix") { + (Get-Item "${env:ProgramFiles(x86)}$suffix").VersionInfo +} elseif (Test-Path "${env:ProgramFiles}$suffix") { + (Get-Item "${env:ProgramFiles}$suffix").VersionInfo +} else { + Write-Host "ERROR: Failed to install Google Chrome." + Write-Host "ERROR: This could be due to insufficient privileges, in which case re-running as Administrator may help." + exit 1 +} diff --git a/node_modules/playwright-core/bin/reinstall_msedge_beta_linux.sh b/node_modules/playwright-core/bin/reinstall_msedge_beta_linux.sh new file mode 100644 index 0000000..e1f156a --- /dev/null +++ b/node_modules/playwright-core/bin/reinstall_msedge_beta_linux.sh @@ -0,0 +1,48 @@ +#!/usr/bin/env bash + +set -e +set -x + +if [[ $(arch) == "aarch64" ]]; then + echo "ERROR: not supported on Linux Arm64" + exit 1 +fi + +if [ -z "$PLAYWRIGHT_HOST_PLATFORM_OVERRIDE" ]; then + if [[ ! -f "/etc/os-release" ]]; then + echo "ERROR: cannot install on unknown linux distribution (/etc/os-release is missing)" + exit 1 + fi + + ID=$(bash -c 'source /etc/os-release && echo $ID') + if [[ "${ID}" != "ubuntu" && "${ID}" != "debian" ]]; then + echo "ERROR: cannot install on $ID distribution - only Ubuntu and Debian are supported" + exit 1 + fi +fi + +# 1. make sure to remove old beta if any. +if dpkg --get-selections | grep -q "^microsoft-edge-beta[[:space:]]*install$" >/dev/null; then + apt-get remove -y microsoft-edge-beta +fi + +# 2. Install curl to download Microsoft gpg key +if ! command -v curl >/dev/null; then + apt-get update + apt-get install -y curl +fi + +# GnuPG is not preinstalled in slim images +if ! command -v gpg >/dev/null; then + apt-get update + apt-get install -y gpg +fi + +# 3. Add the GPG key, the apt repo, update the apt cache, and install the package +curl -L https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor > /tmp/microsoft.gpg +install -o root -g root -m 644 /tmp/microsoft.gpg /etc/apt/trusted.gpg.d/ +sh -c 'echo "deb [arch=amd64] https://packages.microsoft.com/repos/edge stable main" > /etc/apt/sources.list.d/microsoft-edge-dev.list' +rm /tmp/microsoft.gpg +apt-get update && apt-get install -y microsoft-edge-beta + +microsoft-edge-beta --version diff --git a/node_modules/playwright-core/bin/reinstall_msedge_beta_mac.sh b/node_modules/playwright-core/bin/reinstall_msedge_beta_mac.sh new file mode 100644 index 0000000..528a0e7 --- /dev/null +++ b/node_modules/playwright-core/bin/reinstall_msedge_beta_mac.sh @@ -0,0 +1,11 @@ +#!/usr/bin/env bash +set -e +set -x + +cd /tmp +curl -L --retry 3 -o ./msedge_beta.pkg "$1" +# Note: there's no way to uninstall previously installed MSEdge. +# However, running PKG again seems to update installation. +sudo installer -pkg /tmp/msedge_beta.pkg -target / +rm -rf /tmp/msedge_beta.pkg +/Applications/Microsoft\ Edge\ Beta.app/Contents/MacOS/Microsoft\ Edge\ Beta --version diff --git a/node_modules/playwright-core/bin/reinstall_msedge_beta_win.ps1 b/node_modules/playwright-core/bin/reinstall_msedge_beta_win.ps1 new file mode 100644 index 0000000..cce0d0b --- /dev/null +++ b/node_modules/playwright-core/bin/reinstall_msedge_beta_win.ps1 @@ -0,0 +1,23 @@ +$ErrorActionPreference = 'Stop' +$url = $args[0] + +Write-Host "Downloading Microsoft Edge Beta" +$wc = New-Object net.webclient +$msiInstaller = "$env:temp\microsoft-edge-beta.msi" +$wc.Downloadfile($url, $msiInstaller) + +Write-Host "Installing Microsoft Edge Beta" +$arguments = "/i `"$msiInstaller`" /quiet" +Start-Process msiexec.exe -ArgumentList $arguments -Wait +Remove-Item $msiInstaller + +$suffix = "\\Microsoft\\Edge Beta\\Application\\msedge.exe" +if (Test-Path "${env:ProgramFiles(x86)}$suffix") { + (Get-Item "${env:ProgramFiles(x86)}$suffix").VersionInfo +} elseif (Test-Path "${env:ProgramFiles}$suffix") { + (Get-Item "${env:ProgramFiles}$suffix").VersionInfo +} else { + Write-Host "ERROR: Failed to install Microsoft Edge Beta." + Write-Host "ERROR: This could be due to insufficient privileges, in which case re-running as Administrator may help." + exit 1 +} diff --git a/node_modules/playwright-core/bin/reinstall_msedge_dev_linux.sh b/node_modules/playwright-core/bin/reinstall_msedge_dev_linux.sh new file mode 100644 index 0000000..6c1a151 --- /dev/null +++ b/node_modules/playwright-core/bin/reinstall_msedge_dev_linux.sh @@ -0,0 +1,48 @@ +#!/usr/bin/env bash + +set -e +set -x + +if [[ $(arch) == "aarch64" ]]; then + echo "ERROR: not supported on Linux Arm64" + exit 1 +fi + +if [ -z "$PLAYWRIGHT_HOST_PLATFORM_OVERRIDE" ]; then + if [[ ! -f "/etc/os-release" ]]; then + echo "ERROR: cannot install on unknown linux distribution (/etc/os-release is missing)" + exit 1 + fi + + ID=$(bash -c 'source /etc/os-release && echo $ID') + if [[ "${ID}" != "ubuntu" && "${ID}" != "debian" ]]; then + echo "ERROR: cannot install on $ID distribution - only Ubuntu and Debian are supported" + exit 1 + fi +fi + +# 1. make sure to remove old dev if any. +if dpkg --get-selections | grep -q "^microsoft-edge-dev[[:space:]]*install$" >/dev/null; then + apt-get remove -y microsoft-edge-dev +fi + +# 2. Install curl to download Microsoft gpg key +if ! command -v curl >/dev/null; then + apt-get update + apt-get install -y curl +fi + +# GnuPG is not preinstalled in slim images +if ! command -v gpg >/dev/null; then + apt-get update + apt-get install -y gpg +fi + +# 3. Add the GPG key, the apt repo, update the apt cache, and install the package +curl -L https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor > /tmp/microsoft.gpg +install -o root -g root -m 644 /tmp/microsoft.gpg /etc/apt/trusted.gpg.d/ +sh -c 'echo "deb [arch=amd64] https://packages.microsoft.com/repos/edge stable main" > /etc/apt/sources.list.d/microsoft-edge-dev.list' +rm /tmp/microsoft.gpg +apt-get update && apt-get install -y microsoft-edge-dev + +microsoft-edge-dev --version diff --git a/node_modules/playwright-core/bin/reinstall_msedge_dev_mac.sh b/node_modules/playwright-core/bin/reinstall_msedge_dev_mac.sh new file mode 100644 index 0000000..e35ea4e --- /dev/null +++ b/node_modules/playwright-core/bin/reinstall_msedge_dev_mac.sh @@ -0,0 +1,11 @@ +#!/usr/bin/env bash +set -e +set -x + +cd /tmp +curl -L --retry 3 -o ./msedge_dev.pkg "$1" +# Note: there's no way to uninstall previously installed MSEdge. +# However, running PKG again seems to update installation. +sudo installer -pkg /tmp/msedge_dev.pkg -target / +rm -rf /tmp/msedge_dev.pkg +/Applications/Microsoft\ Edge\ Dev.app/Contents/MacOS/Microsoft\ Edge\ Dev --version diff --git a/node_modules/playwright-core/bin/reinstall_msedge_dev_win.ps1 b/node_modules/playwright-core/bin/reinstall_msedge_dev_win.ps1 new file mode 100644 index 0000000..22e6db8 --- /dev/null +++ b/node_modules/playwright-core/bin/reinstall_msedge_dev_win.ps1 @@ -0,0 +1,23 @@ +$ErrorActionPreference = 'Stop' +$url = $args[0] + +Write-Host "Downloading Microsoft Edge Dev" +$wc = New-Object net.webclient +$msiInstaller = "$env:temp\microsoft-edge-dev.msi" +$wc.Downloadfile($url, $msiInstaller) + +Write-Host "Installing Microsoft Edge Dev" +$arguments = "/i `"$msiInstaller`" /quiet" +Start-Process msiexec.exe -ArgumentList $arguments -Wait +Remove-Item $msiInstaller + +$suffix = "\\Microsoft\\Edge Dev\\Application\\msedge.exe" +if (Test-Path "${env:ProgramFiles(x86)}$suffix") { + (Get-Item "${env:ProgramFiles(x86)}$suffix").VersionInfo +} elseif (Test-Path "${env:ProgramFiles}$suffix") { + (Get-Item "${env:ProgramFiles}$suffix").VersionInfo +} else { + Write-Host "ERROR: Failed to install Microsoft Edge Dev." + Write-Host "ERROR: This could be due to insufficient privileges, in which case re-running as Administrator may help." + exit 1 +} diff --git a/node_modules/playwright-core/bin/reinstall_msedge_stable_linux.sh b/node_modules/playwright-core/bin/reinstall_msedge_stable_linux.sh new file mode 100644 index 0000000..93bd766 --- /dev/null +++ b/node_modules/playwright-core/bin/reinstall_msedge_stable_linux.sh @@ -0,0 +1,48 @@ +#!/usr/bin/env bash + +set -e +set -x + +if [[ $(arch) == "aarch64" ]]; then + echo "ERROR: not supported on Linux Arm64" + exit 1 +fi + +if [ -z "$PLAYWRIGHT_HOST_PLATFORM_OVERRIDE" ]; then + if [[ ! -f "/etc/os-release" ]]; then + echo "ERROR: cannot install on unknown linux distribution (/etc/os-release is missing)" + exit 1 + fi + + ID=$(bash -c 'source /etc/os-release && echo $ID') + if [[ "${ID}" != "ubuntu" && "${ID}" != "debian" ]]; then + echo "ERROR: cannot install on $ID distribution - only Ubuntu and Debian are supported" + exit 1 + fi +fi + +# 1. make sure to remove old stable if any. +if dpkg --get-selections | grep -q "^microsoft-edge-stable[[:space:]]*install$" >/dev/null; then + apt-get remove -y microsoft-edge-stable +fi + +# 2. Install curl to download Microsoft gpg key +if ! command -v curl >/dev/null; then + apt-get update + apt-get install -y curl +fi + +# GnuPG is not preinstalled in slim images +if ! command -v gpg >/dev/null; then + apt-get update + apt-get install -y gpg +fi + +# 3. Add the GPG key, the apt repo, update the apt cache, and install the package +curl -L https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor > /tmp/microsoft.gpg +install -o root -g root -m 644 /tmp/microsoft.gpg /etc/apt/trusted.gpg.d/ +sh -c 'echo "deb [arch=amd64] https://packages.microsoft.com/repos/edge stable main" > /etc/apt/sources.list.d/microsoft-edge-stable.list' +rm /tmp/microsoft.gpg +apt-get update && apt-get install -y microsoft-edge-stable + +microsoft-edge-stable --version diff --git a/node_modules/playwright-core/bin/reinstall_msedge_stable_mac.sh b/node_modules/playwright-core/bin/reinstall_msedge_stable_mac.sh new file mode 100644 index 0000000..44e5a56 --- /dev/null +++ b/node_modules/playwright-core/bin/reinstall_msedge_stable_mac.sh @@ -0,0 +1,11 @@ +#!/usr/bin/env bash +set -e +set -x + +cd /tmp +curl -L --retry 3 -o ./msedge_stable.pkg "$1" +# Note: there's no way to uninstall previously installed MSEdge. +# However, running PKG again seems to update installation. +sudo installer -pkg /tmp/msedge_stable.pkg -target / +rm -rf /tmp/msedge_stable.pkg +/Applications/Microsoft\ Edge.app/Contents/MacOS/Microsoft\ Edge --version diff --git a/node_modules/playwright-core/bin/reinstall_msedge_stable_win.ps1 b/node_modules/playwright-core/bin/reinstall_msedge_stable_win.ps1 new file mode 100644 index 0000000..31fdf51 --- /dev/null +++ b/node_modules/playwright-core/bin/reinstall_msedge_stable_win.ps1 @@ -0,0 +1,24 @@ +$ErrorActionPreference = 'Stop' + +$url = $args[0] + +Write-Host "Downloading Microsoft Edge" +$wc = New-Object net.webclient +$msiInstaller = "$env:temp\microsoft-edge-stable.msi" +$wc.Downloadfile($url, $msiInstaller) + +Write-Host "Installing Microsoft Edge" +$arguments = "/i `"$msiInstaller`" /quiet" +Start-Process msiexec.exe -ArgumentList $arguments -Wait +Remove-Item $msiInstaller + +$suffix = "\\Microsoft\\Edge\\Application\\msedge.exe" +if (Test-Path "${env:ProgramFiles(x86)}$suffix") { + (Get-Item "${env:ProgramFiles(x86)}$suffix").VersionInfo +} elseif (Test-Path "${env:ProgramFiles}$suffix") { + (Get-Item "${env:ProgramFiles}$suffix").VersionInfo +} else { + Write-Host "ERROR: Failed to install Microsoft Edge." + Write-Host "ERROR: This could be due to insufficient privileges, in which case re-running as Administrator may help." + exit 1 +} \ No newline at end of file diff --git a/node_modules/playwright-core/browsers.json b/node_modules/playwright-core/browsers.json new file mode 100644 index 0000000..a0651c7 --- /dev/null +++ b/node_modules/playwright-core/browsers.json @@ -0,0 +1,81 @@ +{ + "comment": "Do not edit this file, use utils/roll_browser.js", + "browsers": [ + { + "name": "chromium", + "revision": "1228", + "installByDefault": true, + "browserVersion": "149.0.7827.55", + "title": "Chrome for Testing" + }, + { + "name": "chromium-headless-shell", + "revision": "1228", + "installByDefault": true, + "browserVersion": "149.0.7827.55", + "title": "Chrome Headless Shell" + }, + { + "name": "chromium-tip-of-tree", + "revision": "1432", + "installByDefault": false, + "browserVersion": "151.0.7886.0", + "title": "Chrome Canary for Testing" + }, + { + "name": "chromium-tip-of-tree-headless-shell", + "revision": "1432", + "installByDefault": false, + "browserVersion": "151.0.7886.0", + "title": "Chrome Canary Headless Shell" + }, + { + "name": "firefox", + "revision": "1532", + "installByDefault": true, + "browserVersion": "151.0", + "title": "Firefox" + }, + { + "name": "firefox-beta", + "revision": "1526", + "installByDefault": false, + "browserVersion": "152.0b1", + "title": "Firefox Beta" + }, + { + "name": "webkit", + "revision": "2311", + "installByDefault": true, + "revisionOverrides": { + "mac14": "2251", + "mac14-arm64": "2251", + "debian11-x64": "2105", + "debian11-arm64": "2105", + "ubuntu20.04-x64": "2092", + "ubuntu20.04-arm64": "2092" + }, + "browserVersion": "26.5", + "title": "WebKit" + }, + { + "name": "ffmpeg", + "revision": "1011", + "installByDefault": true, + "revisionOverrides": { + "mac12": "1010", + "mac12-arm64": "1010" + } + }, + { + "name": "winldd", + "revision": "1007", + "installByDefault": false + }, + { + "name": "android", + "revision": "1001", + "installByDefault": false + } + ] +} diff --git a/node_modules/playwright-core/cli.js b/node_modules/playwright-core/cli.js new file mode 100644 index 0000000..f275a03 --- /dev/null +++ b/node_modules/playwright-core/cli.js @@ -0,0 +1,21 @@ +#!/usr/bin/env node +/** + * Copyright (c) Microsoft Corporation. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +const { libCli, libCliTestStub } = require('./lib/coreBundle'); +const { program } = require('./lib/utilsBundle'); +libCli.decorateProgram(program); +libCliTestStub.decorateProgram(program); +program.parse(process.argv); diff --git a/node_modules/playwright-core/index.d.ts b/node_modules/playwright-core/index.d.ts new file mode 100644 index 0000000..97c1493 --- /dev/null +++ b/node_modules/playwright-core/index.d.ts @@ -0,0 +1,17 @@ +/** + * Copyright (c) Microsoft Corporation. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export * from './types/types'; diff --git a/node_modules/playwright-core/index.js b/node_modules/playwright-core/index.js new file mode 100644 index 0000000..9fc51a4 --- /dev/null +++ b/node_modules/playwright-core/index.js @@ -0,0 +1,17 @@ +/** + * Copyright (c) Microsoft Corporation. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +require('./lib/bootstrap'); +module.exports = require('./lib/coreBundle').inprocess.playwright; diff --git a/node_modules/playwright-core/index.mjs b/node_modules/playwright-core/index.mjs new file mode 100644 index 0000000..3b3c75b --- /dev/null +++ b/node_modules/playwright-core/index.mjs @@ -0,0 +1,28 @@ +/** + * Copyright (c) Microsoft Corporation. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import playwright from './index.js'; + +export const chromium = playwright.chromium; +export const firefox = playwright.firefox; +export const webkit = playwright.webkit; +export const selectors = playwright.selectors; +export const devices = playwright.devices; +export const errors = playwright.errors; +export const request = playwright.request; +export const _electron = playwright._electron; +export const _android = playwright._android; +export default playwright; diff --git a/node_modules/playwright-core/lib/bootstrap.js b/node_modules/playwright-core/lib/bootstrap.js new file mode 100644 index 0000000..9825a9a --- /dev/null +++ b/node_modules/playwright-core/lib/bootstrap.js @@ -0,0 +1,88 @@ +"use strict"; +const minimumMajorNodeVersion = 18; +const currentNodeVersion = process.versions.node; +const major = +currentNodeVersion.split(".")[0]; +if (major < minimumMajorNodeVersion) { + console.error( + "You are running Node.js " + currentNodeVersion + `. +Playwright requires Node.js ${minimumMajorNodeVersion} or higher. +Please update your version of Node.js.` + ); + process.exit(1); +} +if (process.env.PW_INSTRUMENT_MODULES) { + const Module = require("module"); + const originalLoad = Module._load; + const root = { name: "", selfMs: 0, totalMs: 0, childrenMs: 0, children: [] }; + let current = root; + const stack = []; + Module._load = function(request, _parent, _isMain) { + const node = { name: request, selfMs: 0, totalMs: 0, childrenMs: 0, children: [] }; + current.children.push(node); + stack.push(current); + current = node; + const start = performance.now(); + let result; + try { + result = originalLoad.apply(this, arguments); + } catch (e) { + current = stack.pop(); + current.children.pop(); + throw e; + } + const duration = performance.now() - start; + node.totalMs = duration; + node.selfMs = Math.max(0, duration - node.childrenMs); + current = stack.pop(); + current.childrenMs += duration; + return result; + }; + process.on("exit", () => { + function printTree(node, prefix, isLast, lines2, depth) { + if (node.totalMs < 1 && depth > 0) + return; + const connector = depth === 0 ? "" : isLast ? "\u2514\u2500\u2500 " : "\u251C\u2500\u2500 "; + const time = `${node.totalMs.toFixed(1).padStart(8)}ms`; + const self = node.children.length ? ` (self: ${node.selfMs.toFixed(1)}ms)` : ""; + lines2.push(`${time} ${prefix}${connector}${node.name}${self}`); + const childPrefix = prefix + (depth === 0 ? "" : isLast ? " " : "\u2502 "); + const sorted2 = node.children.slice().sort((a, b) => b.totalMs - a.totalMs); + for (let i = 0; i < sorted2.length; i++) + printTree(sorted2[i], childPrefix, i === sorted2.length - 1, lines2, depth + 1); + } + let totalModules = 0; + function count(n) { + totalModules++; + n.children.forEach(count); + } + root.children.forEach(count); + const lines = []; + const sorted = root.children.slice().sort((a, b) => b.totalMs - a.totalMs); + for (let i = 0; i < sorted.length; i++) + printTree(sorted[i], "", i === sorted.length - 1, lines, 0); + const totalMs = root.children.reduce((s, c) => s + c.totalMs, 0); + process.stderr.write(` +--- Module load tree: ${totalModules} modules, ${totalMs.toFixed(0)}ms total --- +` + lines.join("\n") + "\n"); + const flat = /* @__PURE__ */ new Map(); + function gather(n) { + const existing = flat.get(n.name); + if (existing) { + existing.selfMs += n.selfMs; + existing.totalMs += n.totalMs; + existing.count++; + } else { + flat.set(n.name, { selfMs: n.selfMs, totalMs: n.totalMs, count: 1 }); + } + n.children.forEach(gather); + } + root.children.forEach(gather); + const top50 = [...flat.entries()].sort((a, b) => b[1].selfMs - a[1].selfMs).slice(0, 50); + const flatLines = top50.map( + ([mod, { selfMs, totalMs: totalMs2, count: count2 }]) => `${selfMs.toFixed(1).padStart(8)}ms self ${totalMs2.toFixed(1).padStart(8)}ms total (x${String(count2).padStart(3)}) ${mod}` + ); + process.stderr.write(` +--- Top 50 modules by self time --- +` + flatLines.join("\n") + "\n"); + }); +} diff --git a/node_modules/playwright-core/lib/coreBundle.js b/node_modules/playwright-core/lib/coreBundle.js new file mode 100644 index 0000000..7d8468f --- /dev/null +++ b/node_modules/playwright-core/lib/coreBundle.js @@ -0,0 +1,73386 @@ +"use strict"; +var __create = Object.create; +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __getProtoOf = Object.getPrototypeOf; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __esm = (fn, res) => function __init() { + return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res; +}; +var __commonJS = (cb, mod) => function __require() { + return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports; +}; +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( + // If the importer is in node compatibility mode or this is not an ESM + // file that has been converted to a CommonJS file using a Babel- + // compatible transform (i.e. "__esModule" has not been set), then set + // "default" to the CommonJS "module.exports" for node compatibility. + isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, + mod +)); +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// packages/isomorphic/ariaSnapshot.ts +function ariaNodesEqual(a, b) { + if (a.role !== b.role || a.name !== b.name) + return false; + if (!ariaPropsEqual(a, b) || hasPointerCursor(a) !== hasPointerCursor(b)) + return false; + const aKeys = Object.keys(a.props); + const bKeys = Object.keys(b.props); + return aKeys.length === bKeys.length && aKeys.every((k) => a.props[k] === b.props[k]); +} +function hasPointerCursor(ariaNode) { + return ariaNode.box.cursor === "pointer"; +} +function ariaPropsEqual(a, b) { + return a.active === b.active && a.checked === b.checked && a.disabled === b.disabled && a.expanded === b.expanded && a.invalid === b.invalid && a.selected === b.selected && a.level === b.level && a.pressed === b.pressed; +} +function parseAriaSnapshotUnsafe(yaml3, text2, options = {}) { + const result2 = parseAriaSnapshot(yaml3, text2, options); + if (result2.errors.length) + throw new Error(result2.errors[0].message); + return result2.fragment; +} +function parseAriaSnapshot(yaml3, text2, options = {}) { + const lineCounter = new yaml3.LineCounter(); + const parseOptions = { + keepSourceTokens: true, + lineCounter, + ...options + }; + const yamlDoc = yaml3.parseDocument(text2, parseOptions); + const errors = []; + const convertRange = (range) => { + return [lineCounter.linePos(range[0]), lineCounter.linePos(range[1])]; + }; + const addError = (error) => { + errors.push({ + message: error.message, + range: [lineCounter.linePos(error.pos[0]), lineCounter.linePos(error.pos[1])] + }); + }; + const convertSeq = (container, seq) => { + for (const item of seq.items) { + const itemIsString = item instanceof yaml3.Scalar && typeof item.value === "string"; + if (itemIsString) { + const childNode = KeyParser.parse(item, parseOptions, errors); + if (childNode) { + container.children = container.children || []; + container.children.push(childNode); + } + continue; + } + const itemIsMap = item instanceof yaml3.YAMLMap; + if (itemIsMap) { + convertMap(container, item); + continue; + } + errors.push({ + message: "Sequence items should be strings or maps", + range: convertRange(item.range || seq.range) + }); + } + }; + const convertMap = (container, map) => { + for (const entry of map.items) { + container.children = container.children || []; + const keyIsString = entry.key instanceof yaml3.Scalar && typeof entry.key.value === "string"; + if (!keyIsString) { + errors.push({ + message: "Only string keys are supported", + range: convertRange(entry.key.range || map.range) + }); + continue; + } + const key = entry.key; + const value2 = entry.value; + if (key.value === "text") { + const valueIsString = value2 instanceof yaml3.Scalar && typeof value2.value === "string"; + if (!valueIsString) { + errors.push({ + message: "Text value should be a string", + range: convertRange(entry.value.range || map.range) + }); + continue; + } + container.children.push({ + kind: "text", + text: textValue(value2.value) + }); + continue; + } + if (key.value === "/children") { + const valueIsString = value2 instanceof yaml3.Scalar && typeof value2.value === "string"; + if (!valueIsString || value2.value !== "contain" && value2.value !== "equal" && value2.value !== "deep-equal") { + errors.push({ + message: 'Strict value should be "contain", "equal" or "deep-equal"', + range: convertRange(entry.value.range || map.range) + }); + continue; + } + container.containerMode = value2.value; + continue; + } + if (key.value.startsWith("/")) { + const valueIsString = value2 instanceof yaml3.Scalar && typeof value2.value === "string"; + if (!valueIsString) { + errors.push({ + message: "Property value should be a string", + range: convertRange(entry.value.range || map.range) + }); + continue; + } + container.props = container.props ?? {}; + container.props[key.value.slice(1)] = textValue(value2.value); + continue; + } + const childNode = KeyParser.parse(key, parseOptions, errors); + if (!childNode) + continue; + const valueIsScalar = value2 instanceof yaml3.Scalar; + if (valueIsScalar) { + const type3 = typeof value2.value; + if (type3 !== "string" && type3 !== "number" && type3 !== "boolean") { + errors.push({ + message: "Node value should be a string or a sequence", + range: convertRange(entry.value.range || map.range) + }); + continue; + } + container.children.push({ + ...childNode, + children: [{ + kind: "text", + text: textValue(String(value2.value)) + }] + }); + continue; + } + const valueIsSequence = value2 instanceof yaml3.YAMLSeq; + if (valueIsSequence) { + container.children.push(childNode); + convertSeq(childNode, value2); + continue; + } + errors.push({ + message: "Map values should be strings or sequences", + range: convertRange(entry.value.range || map.range) + }); + } + }; + const fragment = { kind: "role", role: "fragment" }; + yamlDoc.errors.forEach(addError); + if (errors.length) + return { errors, fragment }; + if (!(yamlDoc.contents instanceof yaml3.YAMLSeq)) { + errors.push({ + message: 'Aria snapshot must be a YAML sequence, elements starting with " -"', + range: yamlDoc.contents ? convertRange(yamlDoc.contents.range) : [{ line: 0, col: 0 }, { line: 0, col: 0 }] + }); + } + if (errors.length) + return { errors, fragment }; + convertSeq(fragment, yamlDoc.contents); + if (errors.length) + return { errors, fragment: emptyFragment }; + if (fragment.children?.length === 1 && (!fragment.containerMode || fragment.containerMode === "contain")) + return { fragment: fragment.children[0], errors: [] }; + return { fragment, errors: [] }; +} +function normalizeWhitespace(text2) { + return text2.replace(/[\u200b\u00ad]/g, "").replace(/[\r\n\s\t]+/g, " ").trim(); +} +function textValue(value2) { + return { + raw: value2, + normalized: normalizeWhitespace(value2) + }; +} +function findNewNode(from, to) { + function fillMap(root, map, position) { + let size = 1; + let childPosition = position + size; + for (const child of root.children || []) { + if (typeof child === "string") { + size++; + childPosition++; + } else { + size += fillMap(child, map, childPosition); + childPosition += size; + } + } + if (!["none", "presentation", "fragment", "iframe", "generic"].includes(root.role) && root.name) { + let byRole = map.get(root.role); + if (!byRole) { + byRole = /* @__PURE__ */ new Map(); + map.set(root.role, byRole); + } + const existing = byRole.get(root.name); + const sizeAndPosition = size * 100 - position; + if (!existing || existing.sizeAndPosition < sizeAndPosition) + byRole.set(root.name, { node: root, sizeAndPosition }); + } + return size; + } + const fromMap = /* @__PURE__ */ new Map(); + if (from) + fillMap(from, fromMap, 0); + const toMap = /* @__PURE__ */ new Map(); + fillMap(to, toMap, 0); + const result2 = []; + for (const [role, byRole] of toMap) { + for (const [name, byName] of byRole) { + const inFrom = fromMap.get(role)?.get(name); + if (!inFrom) + result2.push(byName); + } + } + result2.sort((a, b) => b.sizeAndPosition - a.sizeAndPosition); + return result2[0]?.node; +} +var emptyFragment, KeyParser, ParserError; +var init_ariaSnapshot = __esm({ + "packages/isomorphic/ariaSnapshot.ts"() { + "use strict"; + emptyFragment = { kind: "role", role: "fragment" }; + KeyParser = class _KeyParser { + static parse(text2, options, errors) { + try { + return new _KeyParser(text2.value)._parse(); + } catch (e) { + if (e instanceof ParserError) { + const message = options.prettyErrors === false ? e.message : e.message + ":\n\n" + text2.value + "\n" + " ".repeat(e.pos) + "^\n"; + errors.push({ + message, + range: [options.lineCounter.linePos(text2.range[0]), options.lineCounter.linePos(text2.range[0] + e.pos)] + }); + return null; + } + throw e; + } + } + constructor(input) { + this._input = input; + this._pos = 0; + this._length = input.length; + } + _peek() { + return this._input[this._pos] || ""; + } + _next() { + if (this._pos < this._length) + return this._input[this._pos++]; + return null; + } + _eof() { + return this._pos >= this._length; + } + _isWhitespace() { + return !this._eof() && /\s/.test(this._peek()); + } + _skipWhitespace() { + while (this._isWhitespace()) + this._pos++; + } + _readIdentifier(type3) { + if (this._eof()) + this._throwError(`Unexpected end of input when expecting ${type3}`); + const start3 = this._pos; + while (!this._eof() && /[a-zA-Z]/.test(this._peek())) + this._pos++; + return this._input.slice(start3, this._pos); + } + _readString() { + let result2 = ""; + let escaped2 = false; + while (!this._eof()) { + const ch = this._next(); + if (escaped2) { + result2 += ch; + escaped2 = false; + } else if (ch === "\\") { + escaped2 = true; + } else if (ch === '"') { + return result2; + } else { + result2 += ch; + } + } + this._throwError("Unterminated string"); + } + _throwError(message, offset = 0) { + throw new ParserError(message, offset || this._pos); + } + _readRegex() { + let result2 = ""; + let escaped2 = false; + let insideClass = false; + while (!this._eof()) { + const ch = this._next(); + if (escaped2) { + result2 += ch; + escaped2 = false; + } else if (ch === "\\") { + escaped2 = true; + result2 += ch; + } else if (ch === "/" && !insideClass) { + return { pattern: result2 }; + } else if (ch === "[") { + insideClass = true; + result2 += ch; + } else if (ch === "]" && insideClass) { + result2 += ch; + insideClass = false; + } else { + result2 += ch; + } + } + this._throwError("Unterminated regex"); + } + _readStringOrRegex() { + const ch = this._peek(); + if (ch === '"') { + this._next(); + return normalizeWhitespace(this._readString()); + } + if (ch === "/") { + this._next(); + return this._readRegex(); + } + return null; + } + _readAttributes(result2) { + let errorPos = this._pos; + while (true) { + this._skipWhitespace(); + if (this._peek() === "[") { + this._next(); + this._skipWhitespace(); + errorPos = this._pos; + const flagName = this._readIdentifier("attribute"); + this._skipWhitespace(); + let flagValue = ""; + if (this._peek() === "=") { + this._next(); + this._skipWhitespace(); + errorPos = this._pos; + while (this._peek() !== "]" && !this._isWhitespace() && !this._eof()) + flagValue += this._next(); + } + this._skipWhitespace(); + if (this._peek() !== "]") + this._throwError("Expected ]"); + this._next(); + this._applyAttribute(result2, flagName, flagValue || "true", errorPos); + } else { + break; + } + } + } + _parse() { + this._skipWhitespace(); + const role = this._readIdentifier("role"); + this._skipWhitespace(); + const name = this._readStringOrRegex() || ""; + const result2 = { kind: "role", role, name }; + this._readAttributes(result2); + this._skipWhitespace(); + if (!this._eof()) + this._throwError("Unexpected input"); + return result2; + } + _applyAttribute(node, key, value2, errorPos) { + if (key === "checked") { + this._assert(value2 === "true" || value2 === "false" || value2 === "mixed", 'Value of "checked" attribute must be a boolean or "mixed"', errorPos); + node.checked = value2 === "true" ? true : value2 === "false" ? false : "mixed"; + return; + } + if (key === "disabled") { + this._assert(value2 === "true" || value2 === "false", 'Value of "disabled" attribute must be a boolean', errorPos); + node.disabled = value2 === "true"; + return; + } + if (key === "expanded") { + this._assert(value2 === "true" || value2 === "false", 'Value of "expanded" attribute must be a boolean', errorPos); + node.expanded = value2 === "true"; + return; + } + if (key === "active") { + this._assert(value2 === "true" || value2 === "false", 'Value of "active" attribute must be a boolean', errorPos); + node.active = value2 === "true"; + return; + } + if (key === "invalid") { + this._assert(value2 === "true" || value2 === "false" || value2 === "grammar" || value2 === "spelling", 'Value of "invalid" attribute must be a boolean, "grammar" or "spelling"', errorPos); + node.invalid = value2 === "true" ? true : value2 === "false" ? false : value2; + return; + } + if (key === "level") { + this._assert(!isNaN(Number(value2)), 'Value of "level" attribute must be a number', errorPos); + node.level = Number(value2); + return; + } + if (key === "pressed") { + this._assert(value2 === "true" || value2 === "false" || value2 === "mixed", 'Value of "pressed" attribute must be a boolean or "mixed"', errorPos); + node.pressed = value2 === "true" ? true : value2 === "false" ? false : "mixed"; + return; + } + if (key === "selected") { + this._assert(value2 === "true" || value2 === "false", 'Value of "selected" attribute must be a boolean', errorPos); + node.selected = value2 === "true"; + return; + } + this._assert(false, `Unsupported attribute [${key}]`, errorPos); + } + _assert(value2, message, valuePos) { + if (!value2) + this._throwError(message || "Assertion error", valuePos); + } + }; + ParserError = class extends Error { + constructor(message, pos) { + super(message); + this.pos = pos; + } + }; + } +}); + +// packages/isomorphic/stringUtils.ts +function escapeWithQuotes(text2, char = "'") { + const stringified = JSON.stringify(text2); + const escapedText = stringified.substring(1, stringified.length - 1).replace(/\\"/g, '"'); + if (char === "'") + return char + escapedText.replace(/[']/g, "\\'") + char; + if (char === '"') + return char + escapedText.replace(/["]/g, '\\"') + char; + if (char === "`") + return char + escapedText.replace(/[`]/g, "\\`") + char; + throw new Error("Invalid escape char"); +} +function escapeTemplateString(text2) { + return text2.replace(/\\/g, "\\\\").replace(/`/g, "\\`").replace(/\$\{/g, "\\${"); +} +function isString(obj) { + return typeof obj === "string" || obj instanceof String; +} +function toTitleCase(name) { + return name.charAt(0).toUpperCase() + name.substring(1); +} +function toSnakeCase(name) { + return name.replace(/([a-z0-9])([A-Z])/g, "$1_$2").replace(/([A-Z])([A-Z][a-z])/g, "$1_$2").toLowerCase(); +} +function formatObject(value2, indent = " ", mode = "multiline") { + if (typeof value2 === "string") + return escapeWithQuotes(value2, "'"); + if (Array.isArray(value2)) + return `[${value2.map((o) => formatObject(o)).join(", ")}]`; + if (typeof value2 === "object") { + const keys = Object.keys(value2).filter((key) => key !== "timeout" && value2[key] !== void 0).sort(); + if (!keys.length) + return "{}"; + const tokens = []; + for (const key of keys) + tokens.push(`${key}: ${formatObject(value2[key])}`); + if (mode === "multiline") + return `{ +${tokens.map((t) => indent + t).join(`, +`)} +}`; + return `{ ${tokens.join(", ")} }`; + } + return String(value2); +} +function formatObjectOrVoid(value2, indent = " ") { + const result2 = formatObject(value2, indent); + return result2 === "{}" ? "" : result2; +} +function quoteCSSAttributeValue(text2) { + return `"${text2.replace(/["\\]/g, (char) => "\\" + char)}"`; +} +function cacheNormalizedWhitespaces() { + normalizedWhitespaceCache = /* @__PURE__ */ new Map(); +} +function normalizeWhiteSpace(text2) { + let result2 = normalizedWhitespaceCache?.get(text2); + if (result2 === void 0) { + result2 = text2.replace(/[\u200b\u00ad]/g, "").trim().replace(/\s+/g, " "); + normalizedWhitespaceCache?.set(text2, result2); + } + return result2; +} +function normalizeEscapedRegexQuotes(source11) { + return source11.replace(/(^|[^\\])(\\\\)*\\(['"`])/g, "$1$2$3"); +} +function escapeRegexForSelector(re2) { + if (re2.unicode || re2.unicodeSets) + return String(re2); + return String(re2).replace(/(^|[^\\])(\\\\)*(["'`])/g, "$1$2\\$3").replace(/>>/g, "\\>\\>"); +} +function escapeForTextSelector(text2, exact) { + if (typeof text2 !== "string") + return escapeRegexForSelector(text2); + return `${JSON.stringify(text2)}${exact ? "s" : "i"}`; +} +function escapeForAttributeSelector(value2, exact) { + if (typeof value2 !== "string") + return escapeRegexForSelector(value2); + return `"${value2.replace(/\\/g, "\\\\").replace(/["]/g, '\\"')}"${exact ? "s" : "i"}`; +} +function trimString(input, cap, suffix = "") { + if (input.length <= cap) + return input; + const chars = [...input]; + if (chars.length > cap) + return chars.slice(0, cap - suffix.length).join("") + suffix; + return chars.join(""); +} +function trimStringWithEllipsis(input, cap) { + return trimString(input, cap, "\u2026"); +} +function escapeRegExp(s) { + return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); +} +function escapeHTMLAttribute(s) { + return s.replace(/[&<>"']/ug, (char) => escaped[char]); +} +function escapeHTML(s) { + return s.replace(/[&<]/ug, (char) => escaped[char]); +} +function longestCommonSubstring(s1, s2) { + const n = s1.length; + const m = s2.length; + let maxLen = 0; + let endingIndex = 0; + const dp = Array(n + 1).fill(null).map(() => Array(m + 1).fill(0)); + for (let i = 1; i <= n; i++) { + for (let j = 1; j <= m; j++) { + if (s1[i - 1] === s2[j - 1]) { + dp[i][j] = dp[i - 1][j - 1] + 1; + if (dp[i][j] > maxLen) { + maxLen = dp[i][j]; + endingIndex = i; + } + } + } + } + return s1.slice(endingIndex - maxLen, endingIndex); +} +function parseRegex(regex) { + if (regex[0] !== "/") + throw new Error(`Invalid regex, must start with '/': ${regex}`); + const lastSlash = regex.lastIndexOf("/"); + if (lastSlash <= 0) + throw new Error(`Invalid regex, must end with '/' followed by optional flags: ${regex}`); + const source11 = regex.slice(1, lastSlash); + const flags = regex.slice(lastSlash + 1); + return new RegExp(source11, flags); +} +function tomlBasicString(value2) { + return JSON.stringify(value2); +} +function tomlArray(values) { + return `[${values.map((value2) => tomlBasicString(value2)).join(", ")}]`; +} +function tomlMultilineBasicString(value2) { + const escaped2 = value2.replace(/\\/g, "\\\\").replace(/"""/g, '\\"\\"\\"'); + return `""" +${escaped2} +"""`; +} +function stripAnsiEscapes(str) { + return str.replace(ansiRegex, ""); +} +var normalizedWhitespaceCache, escaped, ansiRegex; +var init_stringUtils = __esm({ + "packages/isomorphic/stringUtils.ts"() { + "use strict"; + escaped = { "&": "&", "<": "<", ">": ">", '"': """, "'": "'" }; + ansiRegex = new RegExp("([\\u001B\\u009B][[\\]()#?]*(?:(?:(?:[a-zA-Z\\d]*(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]*)*)?\\u0007)|(?:(?:\\d{0,4}(?:;\\d{0,4})*)?[\\dA-PR-TZcf-ntqry=><~])))", "g"); + } +}); + +// packages/isomorphic/rtti.ts +function isRegExp(obj) { + return obj instanceof RegExp || Object.prototype.toString.call(obj) === "[object RegExp]"; +} +function isRegexString(value2) { + try { + new RegExp(value2); + return true; + } catch { + return false; + } +} +function isObject(obj) { + return typeof obj === "object" && obj !== null; +} +function isError(obj) { + return obj instanceof Error || obj && Object.getPrototypeOf(obj)?.name === "Error"; +} +var init_rtti = __esm({ + "packages/isomorphic/rtti.ts"() { + "use strict"; + init_stringUtils(); + } +}); + +// packages/isomorphic/expectUtils.ts +function serializeExpectedTextValues(items, options = {}) { + return items.map((i) => ({ + string: isString(i) ? i : void 0, + regexSource: isRegExp(i) ? i.source : void 0, + regexFlags: isRegExp(i) ? i.flags : void 0, + matchSubstring: options.matchSubstring, + ignoreCase: options.ignoreCase, + normalizeWhiteSpace: options.normalizeWhiteSpace + })); +} +var init_expectUtils = __esm({ + "packages/isomorphic/expectUtils.ts"() { + "use strict"; + init_rtti(); + } +}); + +// packages/isomorphic/assert.ts +function assert(value2, message) { + if (!value2) + throw new Error(message || "Assertion error"); +} +var init_assert = __esm({ + "packages/isomorphic/assert.ts"() { + "use strict"; + } +}); + +// packages/isomorphic/base64.ts +function base64ByteLength(data) { + if (!data) + return 0; + const padding = data[data.length - 2] === "=" ? 2 : data[data.length - 1] === "=" ? 1 : 0; + return Math.max(0, Math.floor(data.length * 3 / 4) - padding); +} +var init_base64 = __esm({ + "packages/isomorphic/base64.ts"() { + "use strict"; + } +}); + +// packages/isomorphic/colors.ts +var webColors, noColors, applyStyle; +var init_colors = __esm({ + "packages/isomorphic/colors.ts"() { + "use strict"; + webColors = { + enabled: true, + reset: (text2) => applyStyle(0, 0, text2), + bold: (text2) => applyStyle(1, 22, text2), + dim: (text2) => applyStyle(2, 22, text2), + italic: (text2) => applyStyle(3, 23, text2), + underline: (text2) => applyStyle(4, 24, text2), + inverse: (text2) => applyStyle(7, 27, text2), + hidden: (text2) => applyStyle(8, 28, text2), + strikethrough: (text2) => applyStyle(9, 29, text2), + black: (text2) => applyStyle(30, 39, text2), + red: (text2) => applyStyle(31, 39, text2), + green: (text2) => applyStyle(32, 39, text2), + yellow: (text2) => applyStyle(33, 39, text2), + blue: (text2) => applyStyle(34, 39, text2), + magenta: (text2) => applyStyle(35, 39, text2), + cyan: (text2) => applyStyle(36, 39, text2), + white: (text2) => applyStyle(37, 39, text2), + gray: (text2) => applyStyle(90, 39, text2), + grey: (text2) => applyStyle(90, 39, text2) + }; + noColors = { + enabled: false, + reset: (t) => t, + bold: (t) => t, + dim: (t) => t, + italic: (t) => t, + underline: (t) => t, + inverse: (t) => t, + hidden: (t) => t, + strikethrough: (t) => t, + black: (t) => t, + red: (t) => t, + green: (t) => t, + yellow: (t) => t, + blue: (t) => t, + magenta: (t) => t, + cyan: (t) => t, + white: (t) => t, + gray: (t) => t, + grey: (t) => t + }; + applyStyle = (open5, close3, text2) => `\x1B[${open5}m${text2}\x1B[${close3}m`; + } +}); + +// packages/isomorphic/headers.ts +function headersObjectToArray(headers, separator, setCookieSeparator) { + if (!setCookieSeparator) + setCookieSeparator = separator; + const result2 = []; + for (const name in headers) { + const values = headers[name]; + if (values === void 0) + continue; + if (separator) { + const sep = name.toLowerCase() === "set-cookie" ? setCookieSeparator : separator; + for (const value2 of values.split(sep)) + result2.push({ name, value: value2.trim() }); + } else { + result2.push({ name, value: values }); + } + } + return result2; +} +function headersArrayToObject(headers, lowerCase) { + const result2 = {}; + for (const { name, value: value2 } of headers) + result2[lowerCase ? name.toLowerCase() : name] = value2; + return result2; +} +var init_headers = __esm({ + "packages/isomorphic/headers.ts"() { + "use strict"; + } +}); + +// packages/isomorphic/imageUtils.ts +function padImageToSize(image, size) { + if (image.width === size.width && image.height === size.height) + return image; + const buffer = new Uint8Array(size.width * size.height * 4); + for (let y = 0; y < size.height; y++) { + for (let x = 0; x < size.width; x++) { + const to = (y * size.width + x) * 4; + if (y < image.height && x < image.width) { + const from = (y * image.width + x) * 4; + buffer[to] = image.data[from]; + buffer[to + 1] = image.data[from + 1]; + buffer[to + 2] = image.data[from + 2]; + buffer[to + 3] = image.data[from + 3]; + } else { + buffer[to] = 0; + buffer[to + 1] = 0; + buffer[to + 2] = 0; + buffer[to + 3] = 0; + } + } + } + return { data: Buffer.from(buffer), width: size.width, height: size.height }; +} +function scaleImageToSize(image, size) { + const { data: src, width: w1, height: h1 } = image; + const w2 = Math.max(1, Math.floor(size.width)); + const h2 = Math.max(1, Math.floor(size.height)); + if (w1 === w2 && h1 === h2) + return image; + if (w1 <= 0 || h1 <= 0) + throw new Error("Invalid input image"); + if (size.width <= 0 || size.height <= 0 || !isFinite(size.width) || !isFinite(size.height)) + throw new Error("Invalid output dimensions"); + const clamp = (v, lo, hi) => v < lo ? lo : v > hi ? hi : v; + const weights = (t, o) => { + const t2 = t * t; + const t3 = t2 * t; + o[0] = -0.5 * t + 1 * t2 - 0.5 * t3; + o[1] = 1 - 2.5 * t2 + 1.5 * t3; + o[2] = 0.5 * t + 2 * t2 - 1.5 * t3; + o[3] = -0.5 * t2 + 0.5 * t3; + }; + const srcRowStride = w1 * 4; + const dstRowStride = w2 * 4; + const xOff = new Int32Array(w2 * 4); + const xW = new Float32Array(w2 * 4); + const wx = new Float32Array(4); + const xScale = w1 / w2; + for (let x = 0; x < w2; x++) { + const sx = (x + 0.5) * xScale - 0.5; + const sxi = Math.floor(sx); + const t = sx - sxi; + weights(t, wx); + const b = x * 4; + const i0 = clamp(sxi - 1, 0, w1 - 1); + const i1 = clamp(sxi + 0, 0, w1 - 1); + const i2 = clamp(sxi + 1, 0, w1 - 1); + const i3 = clamp(sxi + 2, 0, w1 - 1); + xOff[b + 0] = i0 << 2; + xOff[b + 1] = i1 << 2; + xOff[b + 2] = i2 << 2; + xOff[b + 3] = i3 << 2; + xW[b + 0] = wx[0]; + xW[b + 1] = wx[1]; + xW[b + 2] = wx[2]; + xW[b + 3] = wx[3]; + } + const yRow = new Int32Array(h2 * 4); + const yW = new Float32Array(h2 * 4); + const wy = new Float32Array(4); + const yScale = h1 / h2; + for (let y = 0; y < h2; y++) { + const sy = (y + 0.5) * yScale - 0.5; + const syi = Math.floor(sy); + const t = sy - syi; + weights(t, wy); + const b = y * 4; + const j0 = clamp(syi - 1, 0, h1 - 1); + const j1 = clamp(syi + 0, 0, h1 - 1); + const j2 = clamp(syi + 1, 0, h1 - 1); + const j3 = clamp(syi + 2, 0, h1 - 1); + yRow[b + 0] = j0 * srcRowStride; + yRow[b + 1] = j1 * srcRowStride; + yRow[b + 2] = j2 * srcRowStride; + yRow[b + 3] = j3 * srcRowStride; + yW[b + 0] = wy[0]; + yW[b + 1] = wy[1]; + yW[b + 2] = wy[2]; + yW[b + 3] = wy[3]; + } + const dst = new Uint8Array(w2 * h2 * 4); + for (let y = 0; y < h2; y++) { + const yb = y * 4; + const rb0 = yRow[yb + 0]; + const rb1 = yRow[yb + 1]; + const rb2 = yRow[yb + 2]; + const rb3 = yRow[yb + 3]; + const wy0 = yW[yb + 0]; + const wy1 = yW[yb + 1]; + const wy2 = yW[yb + 2]; + const wy3 = yW[yb + 3]; + const dstBase = y * dstRowStride; + for (let x = 0; x < w2; x++) { + const xb = x * 4; + const xo0 = xOff[xb + 0]; + const xo1 = xOff[xb + 1]; + const xo2 = xOff[xb + 2]; + const xo3 = xOff[xb + 3]; + const wx0 = xW[xb + 0]; + const wx1 = xW[xb + 1]; + const wx2 = xW[xb + 2]; + const wx3 = xW[xb + 3]; + const di = dstBase + (x << 2); + for (let c = 0; c < 4; c++) { + const r0 = src[rb0 + xo0 + c] * wx0 + src[rb0 + xo1 + c] * wx1 + src[rb0 + xo2 + c] * wx2 + src[rb0 + xo3 + c] * wx3; + const r1 = src[rb1 + xo0 + c] * wx0 + src[rb1 + xo1 + c] * wx1 + src[rb1 + xo2 + c] * wx2 + src[rb1 + xo3 + c] * wx3; + const r2 = src[rb2 + xo0 + c] * wx0 + src[rb2 + xo1 + c] * wx1 + src[rb2 + xo2 + c] * wx2 + src[rb2 + xo3 + c] * wx3; + const r3 = src[rb3 + xo0 + c] * wx0 + src[rb3 + xo1 + c] * wx1 + src[rb3 + xo2 + c] * wx2 + src[rb3 + xo3 + c] * wx3; + const v = r0 * wy0 + r1 * wy1 + r2 * wy2 + r3 * wy3; + dst[di + c] = v < 0 ? 0 : v > 255 ? 255 : v | 0; + } + } + } + return { data: Buffer.from(dst.buffer), width: w2, height: h2 }; +} +var init_imageUtils = __esm({ + "packages/isomorphic/imageUtils.ts"() { + "use strict"; + } +}); + +// packages/isomorphic/jsonSchema.ts +function validate(value2, schema, path59) { + const errors = []; + if (schema.oneOf) { + let bestErrors; + for (const variant of schema.oneOf) { + const variantErrors = validate(value2, variant, path59); + if (variantErrors.length === 0) + return []; + if (!bestErrors || variantErrors.length < bestErrors.length) + bestErrors = variantErrors; + } + if (bestErrors.length === 1 && bestErrors[0].startsWith(`${path59}: expected `)) + return [`${path59}: does not match any of the expected types`]; + return bestErrors; + } + if (schema.type === "string") { + if (typeof value2 !== "string") { + errors.push(`${path59}: expected string, got ${typeof value2}`); + return errors; + } + if (schema.pattern && !cachedRegex(schema.pattern).test(value2)) + errors.push(schema.patternError || `${path59}: must match pattern "${schema.pattern}"`); + return errors; + } + if (schema.type === "array") { + if (!Array.isArray(value2)) { + errors.push(`${path59}: expected array, got ${typeof value2}`); + return errors; + } + if (schema.items) { + for (let i = 0; i < value2.length; i++) + errors.push(...validate(value2[i], schema.items, `${path59}[${i}]`)); + } + return errors; + } + if (schema.type === "object") { + if (!value2 || typeof value2 !== "object" || Array.isArray(value2)) { + errors.push(`${path59}: expected object, got ${Array.isArray(value2) ? "array" : typeof value2}`); + return errors; + } + const obj = value2; + for (const key of schema.required || []) { + if (obj[key] === void 0) + errors.push(`${path59}.${key}: required`); + } + for (const [key, propSchema] of Object.entries(schema.properties || {})) { + if (obj[key] !== void 0) + errors.push(...validate(obj[key], propSchema, `${path59}.${key}`)); + } + return errors; + } + return errors; +} +function cachedRegex(pattern) { + let regex = regexCache.get(pattern); + if (!regex) { + regex = new RegExp(pattern); + regexCache.set(pattern, regex); + } + return regex; +} +var regexCache; +var init_jsonSchema = __esm({ + "packages/isomorphic/jsonSchema.ts"() { + "use strict"; + regexCache = /* @__PURE__ */ new Map(); + } +}); + +// packages/isomorphic/cssTokenizer.ts +function digit(code) { + return between(code, 48, 57); +} +function hexdigit(code) { + return digit(code) || between(code, 65, 70) || between(code, 97, 102); +} +function uppercaseletter(code) { + return between(code, 65, 90); +} +function lowercaseletter(code) { + return between(code, 97, 122); +} +function letter(code) { + return uppercaseletter(code) || lowercaseletter(code); +} +function nonascii(code) { + return code >= 128; +} +function namestartchar(code) { + return letter(code) || nonascii(code) || code === 95; +} +function namechar(code) { + return namestartchar(code) || digit(code) || code === 45; +} +function nonprintable(code) { + return between(code, 0, 8) || code === 11 || between(code, 14, 31) || code === 127; +} +function newline(code) { + return code === 10; +} +function whitespace(code) { + return newline(code) || code === 9 || code === 32; +} +function preprocess(str) { + const codepoints = []; + for (let i = 0; i < str.length; i++) { + let code = str.charCodeAt(i); + if (code === 13 && str.charCodeAt(i + 1) === 10) { + code = 10; + i++; + } + if (code === 13 || code === 12) + code = 10; + if (code === 0) + code = 65533; + if (between(code, 55296, 56319) && between(str.charCodeAt(i + 1), 56320, 57343)) { + const lead = code - 55296; + const trail = str.charCodeAt(i + 1) - 56320; + code = Math.pow(2, 16) + lead * Math.pow(2, 10) + trail; + i++; + } + codepoints.push(code); + } + return codepoints; +} +function stringFromCode(code) { + if (code <= 65535) + return String.fromCharCode(code); + code -= Math.pow(2, 16); + const lead = Math.floor(code / Math.pow(2, 10)) + 55296; + const trail = code % Math.pow(2, 10) + 56320; + return String.fromCharCode(lead) + String.fromCharCode(trail); +} +function tokenize(str1) { + const str = preprocess(str1); + let i = -1; + const tokens = []; + let code; + let line = 0; + let column = 0; + let lastLineLength = 0; + const incrLineno = function() { + line += 1; + lastLineLength = column; + column = 0; + }; + const locStart = { line, column }; + const codepoint = function(i2) { + if (i2 >= str.length) + return -1; + return str[i2]; + }; + const next = function(num) { + if (num === void 0) + num = 1; + if (num > 3) + throw "Spec Error: no more than three codepoints of lookahead."; + return codepoint(i + num); + }; + const consume = function(num) { + if (num === void 0) + num = 1; + i += num; + code = codepoint(i); + if (newline(code)) + incrLineno(); + else + column += num; + return true; + }; + const reconsume = function() { + i -= 1; + if (newline(code)) { + line -= 1; + column = lastLineLength; + } else { + column -= 1; + } + locStart.line = line; + locStart.column = column; + return true; + }; + const eof = function(codepoint2) { + if (codepoint2 === void 0) + codepoint2 = code; + return codepoint2 === -1; + }; + const donothing = function() { + }; + const parseerror = function() { + }; + const consumeAToken = function() { + consumeComments(); + consume(); + if (whitespace(code)) { + while (whitespace(next())) + consume(); + return new WhitespaceToken(); + } else if (code === 34) { + return consumeAStringToken(); + } else if (code === 35) { + if (namechar(next()) || areAValidEscape(next(1), next(2))) { + const token = new HashToken(""); + if (wouldStartAnIdentifier(next(1), next(2), next(3))) + token.type = "id"; + token.value = consumeAName(); + return token; + } else { + return new DelimToken(code); + } + } else if (code === 36) { + if (next() === 61) { + consume(); + return new SuffixMatchToken(); + } else { + return new DelimToken(code); + } + } else if (code === 39) { + return consumeAStringToken(); + } else if (code === 40) { + return new OpenParenToken(); + } else if (code === 41) { + return new CloseParenToken(); + } else if (code === 42) { + if (next() === 61) { + consume(); + return new SubstringMatchToken(); + } else { + return new DelimToken(code); + } + } else if (code === 43) { + if (startsWithANumber()) { + reconsume(); + return consumeANumericToken(); + } else { + return new DelimToken(code); + } + } else if (code === 44) { + return new CommaToken(); + } else if (code === 45) { + if (startsWithANumber()) { + reconsume(); + return consumeANumericToken(); + } else if (next(1) === 45 && next(2) === 62) { + consume(2); + return new CDCToken(); + } else if (startsWithAnIdentifier()) { + reconsume(); + return consumeAnIdentlikeToken(); + } else { + return new DelimToken(code); + } + } else if (code === 46) { + if (startsWithANumber()) { + reconsume(); + return consumeANumericToken(); + } else { + return new DelimToken(code); + } + } else if (code === 58) { + return new ColonToken(); + } else if (code === 59) { + return new SemicolonToken(); + } else if (code === 60) { + if (next(1) === 33 && next(2) === 45 && next(3) === 45) { + consume(3); + return new CDOToken(); + } else { + return new DelimToken(code); + } + } else if (code === 64) { + if (wouldStartAnIdentifier(next(1), next(2), next(3))) + return new AtKeywordToken(consumeAName()); + else + return new DelimToken(code); + } else if (code === 91) { + return new OpenSquareToken(); + } else if (code === 92) { + if (startsWithAValidEscape()) { + reconsume(); + return consumeAnIdentlikeToken(); + } else { + parseerror(); + return new DelimToken(code); + } + } else if (code === 93) { + return new CloseSquareToken(); + } else if (code === 94) { + if (next() === 61) { + consume(); + return new PrefixMatchToken(); + } else { + return new DelimToken(code); + } + } else if (code === 123) { + return new OpenCurlyToken(); + } else if (code === 124) { + if (next() === 61) { + consume(); + return new DashMatchToken(); + } else if (next() === 124) { + consume(); + return new ColumnToken(); + } else { + return new DelimToken(code); + } + } else if (code === 125) { + return new CloseCurlyToken(); + } else if (code === 126) { + if (next() === 61) { + consume(); + return new IncludeMatchToken(); + } else { + return new DelimToken(code); + } + } else if (digit(code)) { + reconsume(); + return consumeANumericToken(); + } else if (namestartchar(code)) { + reconsume(); + return consumeAnIdentlikeToken(); + } else if (eof()) { + return new EOFToken(); + } else { + return new DelimToken(code); + } + }; + const consumeComments = function() { + while (next(1) === 47 && next(2) === 42) { + consume(2); + while (true) { + consume(); + if (code === 42 && next() === 47) { + consume(); + break; + } else if (eof()) { + parseerror(); + return; + } + } + } + }; + const consumeANumericToken = function() { + const num = consumeANumber(); + if (wouldStartAnIdentifier(next(1), next(2), next(3))) { + const token = new DimensionToken(); + token.value = num.value; + token.repr = num.repr; + token.type = num.type; + token.unit = consumeAName(); + return token; + } else if (next() === 37) { + consume(); + const token = new PercentageToken(); + token.value = num.value; + token.repr = num.repr; + return token; + } else { + const token = new NumberToken(); + token.value = num.value; + token.repr = num.repr; + token.type = num.type; + return token; + } + }; + const consumeAnIdentlikeToken = function() { + const str2 = consumeAName(); + if (str2.toLowerCase() === "url" && next() === 40) { + consume(); + while (whitespace(next(1)) && whitespace(next(2))) + consume(); + if (next() === 34 || next() === 39) + return new FunctionToken(str2); + else if (whitespace(next()) && (next(2) === 34 || next(2) === 39)) + return new FunctionToken(str2); + else + return consumeAURLToken(); + } else if (next() === 40) { + consume(); + return new FunctionToken(str2); + } else { + return new IdentToken(str2); + } + }; + const consumeAStringToken = function(endingCodePoint) { + if (endingCodePoint === void 0) + endingCodePoint = code; + let string = ""; + while (consume()) { + if (code === endingCodePoint || eof()) { + return new StringToken(string); + } else if (newline(code)) { + parseerror(); + reconsume(); + return new BadStringToken(); + } else if (code === 92) { + if (eof(next())) + donothing(); + else if (newline(next())) + consume(); + else + string += stringFromCode(consumeEscape()); + } else { + string += stringFromCode(code); + } + } + throw new Error("Internal error"); + }; + const consumeAURLToken = function() { + const token = new URLToken(""); + while (whitespace(next())) + consume(); + if (eof(next())) + return token; + while (consume()) { + if (code === 41 || eof()) { + return token; + } else if (whitespace(code)) { + while (whitespace(next())) + consume(); + if (next() === 41 || eof(next())) { + consume(); + return token; + } else { + consumeTheRemnantsOfABadURL(); + return new BadURLToken(); + } + } else if (code === 34 || code === 39 || code === 40 || nonprintable(code)) { + parseerror(); + consumeTheRemnantsOfABadURL(); + return new BadURLToken(); + } else if (code === 92) { + if (startsWithAValidEscape()) { + token.value += stringFromCode(consumeEscape()); + } else { + parseerror(); + consumeTheRemnantsOfABadURL(); + return new BadURLToken(); + } + } else { + token.value += stringFromCode(code); + } + } + throw new Error("Internal error"); + }; + const consumeEscape = function() { + consume(); + if (hexdigit(code)) { + const digits = [code]; + for (let total = 0; total < 5; total++) { + if (hexdigit(next())) { + consume(); + digits.push(code); + } else { + break; + } + } + if (whitespace(next())) + consume(); + let value2 = parseInt(digits.map(function(x) { + return String.fromCharCode(x); + }).join(""), 16); + if (value2 > maximumallowedcodepoint) + value2 = 65533; + return value2; + } else if (eof()) { + return 65533; + } else { + return code; + } + }; + const areAValidEscape = function(c1, c2) { + if (c1 !== 92) + return false; + if (newline(c2)) + return false; + return true; + }; + const startsWithAValidEscape = function() { + return areAValidEscape(code, next()); + }; + const wouldStartAnIdentifier = function(c1, c2, c3) { + if (c1 === 45) + return namestartchar(c2) || c2 === 45 || areAValidEscape(c2, c3); + else if (namestartchar(c1)) + return true; + else if (c1 === 92) + return areAValidEscape(c1, c2); + else + return false; + }; + const startsWithAnIdentifier = function() { + return wouldStartAnIdentifier(code, next(1), next(2)); + }; + const wouldStartANumber = function(c1, c2, c3) { + if (c1 === 43 || c1 === 45) { + if (digit(c2)) + return true; + if (c2 === 46 && digit(c3)) + return true; + return false; + } else if (c1 === 46) { + if (digit(c2)) + return true; + return false; + } else if (digit(c1)) { + return true; + } else { + return false; + } + }; + const startsWithANumber = function() { + return wouldStartANumber(code, next(1), next(2)); + }; + const consumeAName = function() { + let result2 = ""; + while (consume()) { + if (namechar(code)) { + result2 += stringFromCode(code); + } else if (startsWithAValidEscape()) { + result2 += stringFromCode(consumeEscape()); + } else { + reconsume(); + return result2; + } + } + throw new Error("Internal parse error"); + }; + const consumeANumber = function() { + let repr = ""; + let type3 = "integer"; + if (next() === 43 || next() === 45) { + consume(); + repr += stringFromCode(code); + } + while (digit(next())) { + consume(); + repr += stringFromCode(code); + } + if (next(1) === 46 && digit(next(2))) { + consume(); + repr += stringFromCode(code); + consume(); + repr += stringFromCode(code); + type3 = "number"; + while (digit(next())) { + consume(); + repr += stringFromCode(code); + } + } + const c1 = next(1); + const c2 = next(2); + const c3 = next(3); + if ((c1 === 69 || c1 === 101) && digit(c2)) { + consume(); + repr += stringFromCode(code); + consume(); + repr += stringFromCode(code); + type3 = "number"; + while (digit(next())) { + consume(); + repr += stringFromCode(code); + } + } else if ((c1 === 69 || c1 === 101) && (c2 === 43 || c2 === 45) && digit(c3)) { + consume(); + repr += stringFromCode(code); + consume(); + repr += stringFromCode(code); + consume(); + repr += stringFromCode(code); + type3 = "number"; + while (digit(next())) { + consume(); + repr += stringFromCode(code); + } + } + const value2 = convertAStringToANumber(repr); + return { type: type3, value: value2, repr }; + }; + const convertAStringToANumber = function(string) { + return +string; + }; + const consumeTheRemnantsOfABadURL = function() { + while (consume()) { + if (code === 41 || eof()) { + return; + } else if (startsWithAValidEscape()) { + consumeEscape(); + donothing(); + } else { + donothing(); + } + } + }; + let iterationCount = 0; + while (!eof(next())) { + tokens.push(consumeAToken()); + iterationCount++; + if (iterationCount > str.length * 2) + throw new Error("I'm infinite-looping!"); + } + return tokens; +} +function escapeIdent(string) { + string = "" + string; + let result2 = ""; + const firstcode = string.charCodeAt(0); + for (let i = 0; i < string.length; i++) { + const code = string.charCodeAt(i); + if (code === 0) + throw new InvalidCharacterError("Invalid character: the input contains U+0000."); + if (between(code, 1, 31) || code === 127 || i === 0 && between(code, 48, 57) || i === 1 && between(code, 48, 57) && firstcode === 45) + result2 += "\\" + code.toString(16) + " "; + else if (code >= 128 || code === 45 || code === 95 || between(code, 48, 57) || between(code, 65, 90) || between(code, 97, 122)) + result2 += string[i]; + else + result2 += "\\" + string[i]; + } + return result2; +} +function escapeHash(string) { + string = "" + string; + let result2 = ""; + for (let i = 0; i < string.length; i++) { + const code = string.charCodeAt(i); + if (code === 0) + throw new InvalidCharacterError("Invalid character: the input contains U+0000."); + if (code >= 128 || code === 45 || code === 95 || between(code, 48, 57) || between(code, 65, 90) || between(code, 97, 122)) + result2 += string[i]; + else + result2 += "\\" + code.toString(16) + " "; + } + return result2; +} +function escapeString(string) { + string = "" + string; + let result2 = ""; + for (let i = 0; i < string.length; i++) { + const code = string.charCodeAt(i); + if (code === 0) + throw new InvalidCharacterError("Invalid character: the input contains U+0000."); + if (between(code, 1, 31) || code === 127) + result2 += "\\" + code.toString(16) + " "; + else if (code === 34 || code === 92) + result2 += "\\" + string[i]; + else + result2 += string[i]; + } + return result2; +} +var between, maximumallowedcodepoint, InvalidCharacterError, CSSParserToken, BadStringToken, BadURLToken, WhitespaceToken, CDOToken, CDCToken, ColonToken, SemicolonToken, CommaToken, GroupingToken, OpenCurlyToken, CloseCurlyToken, OpenSquareToken, CloseSquareToken, OpenParenToken, CloseParenToken, IncludeMatchToken, DashMatchToken, PrefixMatchToken, SuffixMatchToken, SubstringMatchToken, ColumnToken, EOFToken, DelimToken, StringValuedToken, IdentToken, FunctionToken, AtKeywordToken, HashToken, StringToken, URLToken, NumberToken, PercentageToken, DimensionToken; +var init_cssTokenizer = __esm({ + "packages/isomorphic/cssTokenizer.ts"() { + "use strict"; + between = function(num, first, last) { + return num >= first && num <= last; + }; + maximumallowedcodepoint = 1114111; + InvalidCharacterError = class extends Error { + constructor(message) { + super(message); + this.name = "InvalidCharacterError"; + } + }; + CSSParserToken = class { + constructor() { + this.tokenType = ""; + } + toJSON() { + return { token: this.tokenType }; + } + toString() { + return this.tokenType; + } + toSource() { + return "" + this; + } + }; + BadStringToken = class extends CSSParserToken { + constructor() { + super(...arguments); + this.tokenType = "BADSTRING"; + } + }; + BadURLToken = class extends CSSParserToken { + constructor() { + super(...arguments); + this.tokenType = "BADURL"; + } + }; + WhitespaceToken = class extends CSSParserToken { + constructor() { + super(...arguments); + this.tokenType = "WHITESPACE"; + } + toString() { + return "WS"; + } + toSource() { + return " "; + } + }; + CDOToken = class extends CSSParserToken { + constructor() { + super(...arguments); + this.tokenType = "CDO"; + } + toSource() { + return ""; + } + }; + ColonToken = class extends CSSParserToken { + constructor() { + super(...arguments); + this.tokenType = ":"; + } + }; + SemicolonToken = class extends CSSParserToken { + constructor() { + super(...arguments); + this.tokenType = ";"; + } + }; + CommaToken = class extends CSSParserToken { + constructor() { + super(...arguments); + this.tokenType = ","; + } + }; + GroupingToken = class extends CSSParserToken { + constructor() { + super(...arguments); + this.value = ""; + this.mirror = ""; + } + }; + OpenCurlyToken = class extends GroupingToken { + constructor() { + super(); + this.tokenType = "{"; + this.value = "{"; + this.mirror = "}"; + } + }; + CloseCurlyToken = class extends GroupingToken { + constructor() { + super(); + this.tokenType = "}"; + this.value = "}"; + this.mirror = "{"; + } + }; + OpenSquareToken = class extends GroupingToken { + constructor() { + super(); + this.tokenType = "["; + this.value = "["; + this.mirror = "]"; + } + }; + CloseSquareToken = class extends GroupingToken { + constructor() { + super(); + this.tokenType = "]"; + this.value = "]"; + this.mirror = "["; + } + }; + OpenParenToken = class extends GroupingToken { + constructor() { + super(); + this.tokenType = "("; + this.value = "("; + this.mirror = ")"; + } + }; + CloseParenToken = class extends GroupingToken { + constructor() { + super(); + this.tokenType = ")"; + this.value = ")"; + this.mirror = "("; + } + }; + IncludeMatchToken = class extends CSSParserToken { + constructor() { + super(...arguments); + this.tokenType = "~="; + } + }; + DashMatchToken = class extends CSSParserToken { + constructor() { + super(...arguments); + this.tokenType = "|="; + } + }; + PrefixMatchToken = class extends CSSParserToken { + constructor() { + super(...arguments); + this.tokenType = "^="; + } + }; + SuffixMatchToken = class extends CSSParserToken { + constructor() { + super(...arguments); + this.tokenType = "$="; + } + }; + SubstringMatchToken = class extends CSSParserToken { + constructor() { + super(...arguments); + this.tokenType = "*="; + } + }; + ColumnToken = class extends CSSParserToken { + constructor() { + super(...arguments); + this.tokenType = "||"; + } + }; + EOFToken = class extends CSSParserToken { + constructor() { + super(...arguments); + this.tokenType = "EOF"; + } + toSource() { + return ""; + } + }; + DelimToken = class extends CSSParserToken { + constructor(code) { + super(); + this.tokenType = "DELIM"; + this.value = ""; + this.value = stringFromCode(code); + } + toString() { + return "DELIM(" + this.value + ")"; + } + toJSON() { + const json = this.constructor.prototype.constructor.prototype.toJSON.call(this); + json.value = this.value; + return json; + } + toSource() { + if (this.value === "\\") + return "\\\n"; + else + return this.value; + } + }; + StringValuedToken = class extends CSSParserToken { + constructor() { + super(...arguments); + this.value = ""; + } + ASCIIMatch(str) { + return this.value.toLowerCase() === str.toLowerCase(); + } + toJSON() { + const json = this.constructor.prototype.constructor.prototype.toJSON.call(this); + json.value = this.value; + return json; + } + }; + IdentToken = class extends StringValuedToken { + constructor(val) { + super(); + this.tokenType = "IDENT"; + this.value = val; + } + toString() { + return "IDENT(" + this.value + ")"; + } + toSource() { + return escapeIdent(this.value); + } + }; + FunctionToken = class extends StringValuedToken { + constructor(val) { + super(); + this.tokenType = "FUNCTION"; + this.value = val; + this.mirror = ")"; + } + toString() { + return "FUNCTION(" + this.value + ")"; + } + toSource() { + return escapeIdent(this.value) + "("; + } + }; + AtKeywordToken = class extends StringValuedToken { + constructor(val) { + super(); + this.tokenType = "AT-KEYWORD"; + this.value = val; + } + toString() { + return "AT(" + this.value + ")"; + } + toSource() { + return "@" + escapeIdent(this.value); + } + }; + HashToken = class extends StringValuedToken { + constructor(val) { + super(); + this.tokenType = "HASH"; + this.value = val; + this.type = "unrestricted"; + } + toString() { + return "HASH(" + this.value + ")"; + } + toJSON() { + const json = this.constructor.prototype.constructor.prototype.toJSON.call(this); + json.value = this.value; + json.type = this.type; + return json; + } + toSource() { + if (this.type === "id") + return "#" + escapeIdent(this.value); + else + return "#" + escapeHash(this.value); + } + }; + StringToken = class extends StringValuedToken { + constructor(val) { + super(); + this.tokenType = "STRING"; + this.value = val; + } + toString() { + return '"' + escapeString(this.value) + '"'; + } + }; + URLToken = class extends StringValuedToken { + constructor(val) { + super(); + this.tokenType = "URL"; + this.value = val; + } + toString() { + return "URL(" + this.value + ")"; + } + toSource() { + return 'url("' + escapeString(this.value) + '")'; + } + }; + NumberToken = class extends CSSParserToken { + constructor() { + super(); + this.tokenType = "NUMBER"; + this.type = "integer"; + this.repr = ""; + } + toString() { + if (this.type === "integer") + return "INT(" + this.value + ")"; + return "NUMBER(" + this.value + ")"; + } + toJSON() { + const json = super.toJSON(); + json.value = this.value; + json.type = this.type; + json.repr = this.repr; + return json; + } + toSource() { + return this.repr; + } + }; + PercentageToken = class extends CSSParserToken { + constructor() { + super(); + this.tokenType = "PERCENTAGE"; + this.repr = ""; + } + toString() { + return "PERCENTAGE(" + this.value + ")"; + } + toJSON() { + const json = this.constructor.prototype.constructor.prototype.toJSON.call(this); + json.value = this.value; + json.repr = this.repr; + return json; + } + toSource() { + return this.repr + "%"; + } + }; + DimensionToken = class extends CSSParserToken { + constructor() { + super(); + this.tokenType = "DIMENSION"; + this.type = "integer"; + this.repr = ""; + this.unit = ""; + } + toString() { + return "DIM(" + this.value + "," + this.unit + ")"; + } + toJSON() { + const json = this.constructor.prototype.constructor.prototype.toJSON.call(this); + json.value = this.value; + json.type = this.type; + json.repr = this.repr; + json.unit = this.unit; + return json; + } + toSource() { + const source11 = this.repr; + let unit = escapeIdent(this.unit); + if (unit[0].toLowerCase() === "e" && (unit[1] === "-" || between(unit.charCodeAt(1), 48, 57))) { + unit = "\\65 " + unit.slice(1, unit.length); + } + return source11 + unit; + } + }; + } +}); + +// packages/isomorphic/cssParser.ts +function isInvalidSelectorError(error) { + return error instanceof InvalidSelectorError; +} +function parseCSS(selector, customNames) { + let tokens; + try { + tokens = tokenize(selector); + if (!(tokens[tokens.length - 1] instanceof EOFToken)) + tokens.push(new EOFToken()); + } catch (e) { + const newMessage = e.message + ` while parsing css selector "${selector}". Did you mean to CSS.escape it?`; + const index = (e.stack || "").indexOf(e.message); + if (index !== -1) + e.stack = e.stack.substring(0, index) + newMessage + e.stack.substring(index + e.message.length); + e.message = newMessage; + throw e; + } + const unsupportedToken = tokens.find((token) => { + return token instanceof AtKeywordToken || token instanceof BadStringToken || token instanceof BadURLToken || token instanceof ColumnToken || token instanceof CDOToken || token instanceof CDCToken || token instanceof SemicolonToken || // TODO: Consider using these for something, e.g. to escape complex strings. + // For example :xpath{ (//div/bar[@attr="foo"])[2]/baz } + // Or this way :xpath( {complex-xpath-goes-here("hello")} ) + token instanceof OpenCurlyToken || token instanceof CloseCurlyToken || // TODO: Consider treating these as strings? + token instanceof URLToken || token instanceof PercentageToken; + }); + if (unsupportedToken) + throw new InvalidSelectorError(`Unsupported token "${unsupportedToken.toSource()}" while parsing css selector "${selector}". Did you mean to CSS.escape it?`); + let pos = 0; + const names = /* @__PURE__ */ new Set(); + function unexpected() { + return new InvalidSelectorError(`Unexpected token "${tokens[pos].toSource()}" while parsing css selector "${selector}". Did you mean to CSS.escape it?`); + } + function skipWhitespace() { + while (tokens[pos] instanceof WhitespaceToken) + pos++; + } + function isIdent(p = pos) { + return tokens[p] instanceof IdentToken; + } + function isString2(p = pos) { + return tokens[p] instanceof StringToken; + } + function isNumber(p = pos) { + return tokens[p] instanceof NumberToken; + } + function isComma(p = pos) { + return tokens[p] instanceof CommaToken; + } + function isOpenParen(p = pos) { + return tokens[p] instanceof OpenParenToken; + } + function isCloseParen(p = pos) { + return tokens[p] instanceof CloseParenToken; + } + function isFunction2(p = pos) { + return tokens[p] instanceof FunctionToken; + } + function isStar(p = pos) { + return tokens[p] instanceof DelimToken && tokens[p].value === "*"; + } + function isEOF(p = pos) { + return tokens[p] instanceof EOFToken; + } + function isClauseCombinator(p = pos) { + return tokens[p] instanceof DelimToken && [">", "+", "~"].includes(tokens[p].value); + } + function isSelectorClauseEnd(p = pos) { + return isComma(p) || isCloseParen(p) || isEOF(p) || isClauseCombinator(p) || tokens[p] instanceof WhitespaceToken; + } + function consumeFunctionArguments() { + const result3 = [consumeArgument()]; + while (true) { + skipWhitespace(); + if (!isComma()) + break; + pos++; + result3.push(consumeArgument()); + } + return result3; + } + function consumeArgument() { + skipWhitespace(); + if (isNumber()) + return tokens[pos++].value; + if (isString2()) + return tokens[pos++].value; + return consumeComplexSelector(); + } + function consumeComplexSelector() { + const result3 = { simples: [] }; + skipWhitespace(); + if (isClauseCombinator()) { + result3.simples.push({ selector: { functions: [{ name: "scope", args: [] }] }, combinator: "" }); + } else { + result3.simples.push({ selector: consumeSimpleSelector(), combinator: "" }); + } + while (true) { + skipWhitespace(); + if (isClauseCombinator()) { + result3.simples[result3.simples.length - 1].combinator = tokens[pos++].value; + skipWhitespace(); + } else if (isSelectorClauseEnd()) { + break; + } + result3.simples.push({ combinator: "", selector: consumeSimpleSelector() }); + } + return result3; + } + function consumeSimpleSelector() { + let rawCSSString = ""; + const functions = []; + while (!isSelectorClauseEnd()) { + if (isIdent() || isStar()) { + rawCSSString += tokens[pos++].toSource(); + } else if (tokens[pos] instanceof HashToken) { + rawCSSString += tokens[pos++].toSource(); + } else if (tokens[pos] instanceof DelimToken && tokens[pos].value === ".") { + pos++; + if (isIdent()) + rawCSSString += "." + tokens[pos++].toSource(); + else + throw unexpected(); + } else if (tokens[pos] instanceof ColonToken) { + pos++; + if (isIdent()) { + if (!customNames.has(tokens[pos].value.toLowerCase())) { + rawCSSString += ":" + tokens[pos++].toSource(); + } else { + const name = tokens[pos++].value.toLowerCase(); + functions.push({ name, args: [] }); + names.add(name); + } + } else if (isFunction2()) { + const name = tokens[pos++].value.toLowerCase(); + if (!customNames.has(name)) { + rawCSSString += `:${name}(${consumeBuiltinFunctionArguments()})`; + } else { + functions.push({ name, args: consumeFunctionArguments() }); + names.add(name); + } + skipWhitespace(); + if (!isCloseParen()) + throw unexpected(); + pos++; + } else { + throw unexpected(); + } + } else if (tokens[pos] instanceof OpenSquareToken) { + rawCSSString += "["; + pos++; + while (!(tokens[pos] instanceof CloseSquareToken) && !isEOF()) + rawCSSString += tokens[pos++].toSource(); + if (!(tokens[pos] instanceof CloseSquareToken)) + throw unexpected(); + rawCSSString += "]"; + pos++; + } else { + throw unexpected(); + } + } + if (!rawCSSString && !functions.length) + throw unexpected(); + return { css: rawCSSString || void 0, functions }; + } + function consumeBuiltinFunctionArguments() { + let s = ""; + let balance = 1; + while (!isEOF()) { + if (isOpenParen() || isFunction2()) + balance++; + if (isCloseParen()) + balance--; + if (!balance) + break; + s += tokens[pos++].toSource(); + } + return s; + } + const result2 = consumeFunctionArguments(); + if (!isEOF()) + throw unexpected(); + if (result2.some((arg) => typeof arg !== "object" || !("simples" in arg))) + throw new InvalidSelectorError(`Error while parsing css selector "${selector}". Did you mean to CSS.escape it?`); + return { selector: result2, names: Array.from(names) }; +} +function serializeSelector(args) { + return args.map((arg) => { + if (typeof arg === "string") + return `"${arg}"`; + if (typeof arg === "number") + return String(arg); + return arg.simples.map(({ selector, combinator }) => { + let s = selector.css || ""; + s = s + selector.functions.map((func) => `:${func.name}(${serializeSelector(func.args)})`).join(""); + if (combinator) + s += " " + combinator; + return s; + }).join(" "); + }).join(", "); +} +var InvalidSelectorError; +var init_cssParser = __esm({ + "packages/isomorphic/cssParser.ts"() { + "use strict"; + init_cssTokenizer(); + InvalidSelectorError = class extends Error { + }; + } +}); + +// packages/isomorphic/selectorParser.ts +function parseSelector(selector) { + const parsedStrings = parseSelectorString(selector); + const parts = []; + for (const part of parsedStrings.parts) { + if (part.name === "css" || part.name === "css:light") { + if (part.name === "css:light") + part.body = ":light(" + part.body + ")"; + const parsedCSS = parseCSS(part.body, customCSSNames); + parts.push({ + name: "css", + body: parsedCSS.selector, + source: part.body + }); + continue; + } + if (kNestedSelectorNames.has(part.name)) { + let innerSelector; + let distance; + try { + const unescaped = JSON.parse("[" + part.body + "]"); + if (!Array.isArray(unescaped) || unescaped.length < 1 || unescaped.length > 2 || typeof unescaped[0] !== "string") + throw new InvalidSelectorError(`Malformed selector: ${part.name}=` + part.body); + innerSelector = unescaped[0]; + if (unescaped.length === 2) { + if (typeof unescaped[1] !== "number" || !kNestedSelectorNamesWithDistance.has(part.name)) + throw new InvalidSelectorError(`Malformed selector: ${part.name}=` + part.body); + distance = unescaped[1]; + } + } catch (e) { + throw new InvalidSelectorError(`Malformed selector: ${part.name}=` + part.body); + } + const nested = { name: part.name, source: part.body, body: { parsed: parseSelector(innerSelector), distance } }; + const lastFrame = [...nested.body.parsed.parts].reverse().find((part2) => part2.name === "internal:control" && part2.body === "enter-frame"); + const lastFrameIndex = lastFrame ? nested.body.parsed.parts.indexOf(lastFrame) : -1; + if (lastFrameIndex !== -1 && selectorPartsEqual(nested.body.parsed.parts.slice(0, lastFrameIndex + 1), parts.slice(0, lastFrameIndex + 1))) + nested.body.parsed.parts.splice(0, lastFrameIndex + 1); + parts.push(nested); + continue; + } + parts.push({ ...part, source: part.body }); + } + if (kNestedSelectorNames.has(parts[0].name)) + throw new InvalidSelectorError(`"${parts[0].name}" selector cannot be first`); + return { + capture: parsedStrings.capture, + parts + }; +} +function splitSelectorByFrame(selectorText) { + const selector = parseSelector(selectorText); + const result2 = []; + let chunk = { + parts: [] + }; + let chunkStartIndex = 0; + for (let i = 0; i < selector.parts.length; ++i) { + const part = selector.parts[i]; + if (part.name === "internal:control" && part.body === "enter-frame") { + if (!chunk.parts.length) + throw new InvalidSelectorError("Selector cannot start with entering frame, select the iframe first"); + result2.push(chunk); + chunk = { parts: [] }; + chunkStartIndex = i + 1; + continue; + } + if (selector.capture === i) + chunk.capture = i - chunkStartIndex; + chunk.parts.push(part); + } + if (!chunk.parts.length) + throw new InvalidSelectorError(`Selector cannot end with entering frame, while parsing selector ${selectorText}`); + result2.push(chunk); + if (typeof selector.capture === "number" && typeof result2[result2.length - 1].capture !== "number") + throw new InvalidSelectorError(`Can not capture the selector before diving into the frame. Only use * after the last frame has been selected`); + return result2; +} +function selectorPartsEqual(list1, list2) { + return stringifySelector({ parts: list1 }) === stringifySelector({ parts: list2 }); +} +function stringifySelector(selector, forceEngineName) { + if (typeof selector === "string") + return selector; + return selector.parts.map((p, i) => { + let includeEngine = true; + if (!forceEngineName && i !== selector.capture) { + if (p.name === "css") + includeEngine = false; + else if (p.name === "xpath" && p.source.startsWith("//") || p.source.startsWith("..")) + includeEngine = false; + } + const prefix = includeEngine ? p.name + "=" : ""; + return `${i === selector.capture ? "*" : ""}${prefix}${p.source}`; + }).join(" >> "); +} +function visitAllSelectorParts(selector, visitor) { + const visit = (selector2, nested) => { + for (const part of selector2.parts) { + visitor(part, nested); + if (kNestedSelectorNames.has(part.name)) + visit(part.body.parsed, true); + } + }; + visit(selector, false); +} +function parseSelectorString(selector) { + let index = 0; + let quote5; + let start3 = 0; + const result2 = { parts: [] }; + const append = () => { + const part = selector.substring(start3, index).trim(); + const eqIndex = part.indexOf("="); + let name; + let body; + if (eqIndex !== -1 && part.substring(0, eqIndex).trim().match(/^[a-zA-Z_0-9-+:*]+$/)) { + name = part.substring(0, eqIndex).trim(); + body = part.substring(eqIndex + 1); + } else if (part.length > 1 && part[0] === '"' && part[part.length - 1] === '"') { + name = "text"; + body = part; + } else if (part.length > 1 && part[0] === "'" && part[part.length - 1] === "'") { + name = "text"; + body = part; + } else if (/^\(*\/\//.test(part) || part.startsWith("..")) { + name = "xpath"; + body = part; + } else { + name = "css"; + body = part; + } + let capture = false; + if (name[0] === "*") { + capture = true; + name = name.substring(1); + } + result2.parts.push({ name, body }); + if (capture) { + if (result2.capture !== void 0) + throw new InvalidSelectorError(`Only one of the selectors can capture using * modifier`); + result2.capture = result2.parts.length - 1; + } + }; + if (!selector.includes(">>")) { + index = selector.length; + append(); + return result2; + } + const shouldIgnoreTextSelectorQuote = () => { + const prefix = selector.substring(start3, index); + const match = prefix.match(/^\s*text\s*=(.*)$/); + return !!match && !!match[1]; + }; + while (index < selector.length) { + const c = selector[index]; + if (c === "\\" && index + 1 < selector.length) { + index += 2; + } else if (c === quote5) { + quote5 = void 0; + index++; + } else if (!quote5 && (c === '"' || c === "'" || c === "`") && !shouldIgnoreTextSelectorQuote()) { + quote5 = c; + index++; + } else if (!quote5 && c === ">" && selector[index + 1] === ">") { + append(); + index += 2; + start3 = index; + } else { + index++; + } + } + append(); + return result2; +} +function parseAttributeSelector(selector, allowUnquotedStrings) { + let wp = 0; + let EOL = selector.length === 0; + const next = () => selector[wp] || ""; + const eat1 = () => { + const result3 = next(); + ++wp; + EOL = wp >= selector.length; + return result3; + }; + const syntaxError = (stage) => { + if (EOL) + throw new InvalidSelectorError(`Unexpected end of selector while parsing selector \`${selector}\``); + throw new InvalidSelectorError(`Error while parsing selector \`${selector}\` - unexpected symbol "${next()}" at position ${wp}` + (stage ? " during " + stage : "")); + }; + function skipSpaces() { + while (!EOL && /\s/.test(next())) + eat1(); + } + function isCSSNameChar(char) { + return char >= "\x80" || char >= "0" && char <= "9" || char >= "A" && char <= "Z" || char >= "a" && char <= "z" || char >= "0" && char <= "9" || char === "_" || char === "-"; + } + function readIdentifier() { + let result3 = ""; + skipSpaces(); + while (!EOL && isCSSNameChar(next())) + result3 += eat1(); + return result3; + } + function readQuotedString(quote5) { + let result3 = eat1(); + if (result3 !== quote5) + syntaxError("parsing quoted string"); + while (!EOL && next() !== quote5) { + if (next() === "\\") + eat1(); + result3 += eat1(); + } + if (next() !== quote5) + syntaxError("parsing quoted string"); + result3 += eat1(); + return result3; + } + function readRegularExpression() { + if (eat1() !== "/") + syntaxError("parsing regular expression"); + let source11 = ""; + let inClass = false; + while (!EOL) { + if (next() === "\\") { + source11 += eat1(); + if (EOL) + syntaxError("parsing regular expression"); + } else if (inClass && next() === "]") { + inClass = false; + } else if (!inClass && next() === "[") { + inClass = true; + } else if (!inClass && next() === "/") { + break; + } + source11 += eat1(); + } + if (eat1() !== "/") + syntaxError("parsing regular expression"); + let flags = ""; + while (!EOL && next().match(/[dgimsuy]/)) + flags += eat1(); + try { + return new RegExp(source11, flags); + } catch (e) { + throw new InvalidSelectorError(`Error while parsing selector \`${selector}\`: ${e.message}`); + } + } + function readAttributeToken() { + let token = ""; + skipSpaces(); + if (next() === `'` || next() === `"`) + token = readQuotedString(next()).slice(1, -1); + else + token = readIdentifier(); + if (!token) + syntaxError("parsing property path"); + return token; + } + function readOperator() { + skipSpaces(); + let op = ""; + if (!EOL) + op += eat1(); + if (!EOL && op !== "=") + op += eat1(); + if (!["=", "*=", "^=", "$=", "|=", "~="].includes(op)) + syntaxError("parsing operator"); + return op; + } + function readAttribute() { + eat1(); + const jsonPath = []; + jsonPath.push(readAttributeToken()); + skipSpaces(); + while (next() === ".") { + eat1(); + jsonPath.push(readAttributeToken()); + skipSpaces(); + } + if (next() === "]") { + eat1(); + return { name: jsonPath.join("."), jsonPath, op: "", value: null, caseSensitive: false }; + } + const operator = readOperator(); + let value2 = void 0; + let caseSensitive = true; + skipSpaces(); + if (next() === "/") { + if (operator !== "=") + throw new InvalidSelectorError(`Error while parsing selector \`${selector}\` - cannot use ${operator} in attribute with regular expression`); + value2 = readRegularExpression(); + } else if (next() === `'` || next() === `"`) { + value2 = readQuotedString(next()).slice(1, -1); + skipSpaces(); + if (next() === "i" || next() === "I") { + caseSensitive = false; + eat1(); + } else if (next() === "s" || next() === "S") { + caseSensitive = true; + eat1(); + } + } else { + value2 = ""; + while (!EOL && (isCSSNameChar(next()) || next() === "+" || next() === ".")) + value2 += eat1(); + if (value2 === "true") { + value2 = true; + } else if (value2 === "false") { + value2 = false; + } else { + if (!allowUnquotedStrings) { + value2 = +value2; + if (Number.isNaN(value2)) + syntaxError("parsing attribute value"); + } + } + } + skipSpaces(); + if (next() !== "]") + syntaxError("parsing attribute value"); + eat1(); + if (operator !== "=" && typeof value2 !== "string") + throw new InvalidSelectorError(`Error while parsing selector \`${selector}\` - cannot use ${operator} in attribute with non-string matching value - ${value2}`); + return { name: jsonPath.join("."), jsonPath, op: operator, value: value2, caseSensitive }; + } + const result2 = { + name: "", + attributes: [] + }; + result2.name = readIdentifier(); + skipSpaces(); + while (next() === "[") { + result2.attributes.push(readAttribute()); + skipSpaces(); + } + if (!EOL) + syntaxError(void 0); + if (!result2.name && !result2.attributes.length) + throw new InvalidSelectorError(`Error while parsing selector \`${selector}\` - selector cannot be empty`); + return result2; +} +var kNestedSelectorNames, kNestedSelectorNamesWithDistance, customCSSNames; +var init_selectorParser = __esm({ + "packages/isomorphic/selectorParser.ts"() { + "use strict"; + init_cssParser(); + init_cssParser(); + kNestedSelectorNames = /* @__PURE__ */ new Set(["internal:has", "internal:has-not", "internal:and", "internal:or", "internal:chain", "left-of", "right-of", "above", "below", "near"]); + kNestedSelectorNamesWithDistance = /* @__PURE__ */ new Set(["left-of", "right-of", "above", "below", "near"]); + customCSSNames = /* @__PURE__ */ new Set(["not", "is", "where", "has", "scope", "light", "visible", "text", "text-matches", "text-is", "has-text", "above", "below", "right-of", "left-of", "near", "nth-match"]); + } +}); + +// packages/isomorphic/locatorGenerators.ts +function asLocatorDescription(lang, selector) { + try { + const parsed = parseSelector(selector); + const customDescription = parseCustomDescription(parsed); + if (customDescription) + return customDescription; + return innerAsLocators(new generators[lang](), parsed, false, 1)[0]; + } catch (e) { + return selector; + } +} +function locatorCustomDescription(selector) { + try { + const parsed = parseSelector(selector); + return parseCustomDescription(parsed); + } catch (e) { + return void 0; + } +} +function parseCustomDescription(parsed) { + const lastPart = parsed.parts[parsed.parts.length - 1]; + if (lastPart?.name === "internal:describe") { + const description = JSON.parse(lastPart.body); + if (typeof description === "string") + return description; + } + return void 0; +} +function asLocator(lang, selector, isFrameLocator = false) { + return asLocators(lang, selector, isFrameLocator, 1)[0]; +} +function asLocators(lang, selector, isFrameLocator = false, maxOutputSize = 20, preferredQuote) { + try { + return innerAsLocators(new generators[lang](preferredQuote), parseSelector(selector), isFrameLocator, maxOutputSize); + } catch (e) { + return [selector]; + } +} +function innerAsLocators(factory, parsed, isFrameLocator = false, maxOutputSize = 20) { + const parts = [...parsed.parts]; + const tokens = []; + let nextBase = isFrameLocator ? "frame-locator" : "page"; + for (let index = 0; index < parts.length; index++) { + const part = parts[index]; + const base = nextBase; + nextBase = "locator"; + if (part.name === "internal:describe") + continue; + if (part.name === "nth") { + if (part.body === "0") + tokens.push([factory.generateLocator(base, "first", ""), factory.generateLocator(base, "nth", "0")]); + else if (part.body === "-1") + tokens.push([factory.generateLocator(base, "last", ""), factory.generateLocator(base, "nth", "-1")]); + else + tokens.push([factory.generateLocator(base, "nth", part.body)]); + continue; + } + if (part.name === "visible") { + tokens.push([factory.generateLocator(base, "visible", part.body), factory.generateLocator(base, "default", `visible=${part.body}`)]); + continue; + } + if (part.name === "internal:text") { + const { exact, text: text2 } = detectExact(part.body); + tokens.push([factory.generateLocator(base, "text", text2, { exact })]); + continue; + } + if (part.name === "internal:has-text") { + const { exact, text: text2 } = detectExact(part.body); + if (!exact) { + tokens.push([factory.generateLocator(base, "has-text", text2, { exact })]); + continue; + } + } + if (part.name === "internal:has-not-text") { + const { exact, text: text2 } = detectExact(part.body); + if (!exact) { + tokens.push([factory.generateLocator(base, "has-not-text", text2, { exact })]); + continue; + } + } + if (part.name === "internal:has") { + const inners = innerAsLocators(factory, part.body.parsed, false, maxOutputSize); + tokens.push(inners.map((inner) => factory.generateLocator(base, "has", inner))); + continue; + } + if (part.name === "internal:has-not") { + const inners = innerAsLocators(factory, part.body.parsed, false, maxOutputSize); + tokens.push(inners.map((inner) => factory.generateLocator(base, "hasNot", inner))); + continue; + } + if (part.name === "internal:and") { + const inners = innerAsLocators(factory, part.body.parsed, false, maxOutputSize); + tokens.push(inners.map((inner) => factory.generateLocator(base, "and", inner))); + continue; + } + if (part.name === "internal:or") { + const inners = innerAsLocators(factory, part.body.parsed, false, maxOutputSize); + tokens.push(inners.map((inner) => factory.generateLocator(base, "or", inner))); + continue; + } + if (part.name === "internal:chain") { + const inners = innerAsLocators(factory, part.body.parsed, false, maxOutputSize); + tokens.push(inners.map((inner) => factory.generateLocator(base, "chain", inner))); + continue; + } + if (part.name === "internal:label") { + const { exact, text: text2 } = detectExact(part.body); + tokens.push([factory.generateLocator(base, "label", text2, { exact })]); + continue; + } + if (part.name === "internal:role") { + const attrSelector = parseAttributeSelector(part.body, true); + const options = { attrs: [] }; + for (const attr of attrSelector.attributes) { + if (attr.name === "name") { + if (options.exact !== void 0 && options.exact !== attr.caseSensitive) + throw new Error(`Conflicting exactness in internal:role selector: ${stringifySelector({ parts: [part] })}`); + options.exact = attr.caseSensitive; + options.name = attr.value; + } else if (attr.name === "description") { + if (options.exact !== void 0 && options.exact !== attr.caseSensitive) + throw new Error(`Conflicting exactness in internal:role selector: ${stringifySelector({ parts: [part] })}`); + options.exact = attr.caseSensitive; + options.description = attr.value; + } else { + if (attr.name === "level" && typeof attr.value === "string") + attr.value = +attr.value; + options.attrs.push({ name: attr.name === "include-hidden" ? "includeHidden" : attr.name, value: attr.value }); + } + } + tokens.push([factory.generateLocator(base, "role", attrSelector.name, options)]); + continue; + } + if (part.name === "internal:testid") { + const attrSelector = parseAttributeSelector(part.body, true); + const { value: value2 } = attrSelector.attributes[0]; + tokens.push([factory.generateLocator(base, "test-id", value2)]); + continue; + } + if (part.name === "internal:attr") { + const attrSelector = parseAttributeSelector(part.body, true); + const { name, value: value2, caseSensitive } = attrSelector.attributes[0]; + const text2 = value2; + const exact = !!caseSensitive; + if (name === "placeholder") { + tokens.push([factory.generateLocator(base, "placeholder", text2, { exact })]); + continue; + } + if (name === "alt") { + tokens.push([factory.generateLocator(base, "alt", text2, { exact })]); + continue; + } + if (name === "title") { + tokens.push([factory.generateLocator(base, "title", text2, { exact })]); + continue; + } + } + if (part.name === "internal:control" && part.body === "enter-frame") { + const lastTokens = tokens[tokens.length - 1]; + const lastPart = parts[index - 1]; + const transformed = lastTokens.map((token) => factory.chainLocators([token, factory.generateLocator(base, "frame", "")])); + if (["xpath", "css"].includes(lastPart.name)) { + transformed.push( + factory.generateLocator(base, "frame-locator", stringifySelector({ parts: [lastPart] })), + factory.generateLocator(base, "frame-locator", stringifySelector({ parts: [lastPart] }, true)) + ); + } + lastTokens.splice(0, lastTokens.length, ...transformed); + nextBase = "frame-locator"; + continue; + } + const nextPart = parts[index + 1]; + const selectorPart = stringifySelector({ parts: [part] }); + const locatorPart = factory.generateLocator(base, "default", selectorPart); + if (nextPart && ["internal:has-text", "internal:has-not-text"].includes(nextPart.name)) { + const { exact, text: text2 } = detectExact(nextPart.body); + if (!exact) { + const nextLocatorPart = factory.generateLocator("locator", nextPart.name === "internal:has-text" ? "has-text" : "has-not-text", text2, { exact }); + const options = {}; + if (nextPart.name === "internal:has-text") + options.hasText = text2; + else + options.hasNotText = text2; + const combinedPart = factory.generateLocator(base, "default", selectorPart, options); + tokens.push([factory.chainLocators([locatorPart, nextLocatorPart]), combinedPart]); + index++; + continue; + } + } + let locatorPartWithEngine; + if (["xpath", "css"].includes(part.name)) { + const selectorPart2 = stringifySelector( + { parts: [part] }, + /* forceEngineName */ + true + ); + locatorPartWithEngine = factory.generateLocator(base, "default", selectorPart2); + } + tokens.push([locatorPart, locatorPartWithEngine].filter(Boolean)); + } + return combineTokens(factory, tokens, maxOutputSize); +} +function combineTokens(factory, tokens, maxOutputSize) { + const currentTokens = tokens.map(() => ""); + const result2 = []; + const visit = (index) => { + if (index === tokens.length) { + result2.push(factory.chainLocators(currentTokens)); + return result2.length < maxOutputSize; + } + for (const taken of tokens[index]) { + currentTokens[index] = taken; + if (!visit(index + 1)) + return false; + } + return true; + }; + visit(0); + return result2; +} +function detectExact(text2) { + let exact = false; + const match = text2.match(/^\/(.*)\/([igm]*)$/); + if (match) + return { text: new RegExp(match[1], match[2]) }; + if (text2.endsWith('"')) { + text2 = JSON.parse(text2); + exact = true; + } else if (text2.endsWith('"s')) { + text2 = JSON.parse(text2.substring(0, text2.length - 1)); + exact = true; + } else if (text2.endsWith('"i')) { + text2 = JSON.parse(text2.substring(0, text2.length - 1)); + exact = false; + } + return { exact, text: text2 }; +} +function isRegExp2(obj) { + return obj instanceof RegExp; +} +var JavaScriptLocatorFactory, PythonLocatorFactory, JavaLocatorFactory, CSharpLocatorFactory, JsonlLocatorFactory, generators; +var init_locatorGenerators = __esm({ + "packages/isomorphic/locatorGenerators.ts"() { + "use strict"; + init_selectorParser(); + init_stringUtils(); + JavaScriptLocatorFactory = class { + constructor(preferredQuote) { + this.preferredQuote = preferredQuote; + } + generateLocator(base, kind, body, options = {}) { + switch (kind) { + case "default": + if (options.hasText !== void 0) + return `locator(${this.quote(body)}, { hasText: ${this.toHasText(options.hasText)} })`; + if (options.hasNotText !== void 0) + return `locator(${this.quote(body)}, { hasNotText: ${this.toHasText(options.hasNotText)} })`; + return `locator(${this.quote(body)})`; + case "frame-locator": + return `frameLocator(${this.quote(body)})`; + case "frame": + return `contentFrame()`; + case "nth": + return `nth(${body})`; + case "first": + return `first()`; + case "last": + return `last()`; + case "visible": + return `filter({ visible: ${body === "true" ? "true" : "false"} })`; + case "role": + const attrs = []; + if (isRegExp2(options.name)) + attrs.push(`name: ${this.regexToSourceString(options.name)}`); + else if (typeof options.name === "string") + attrs.push(`name: ${this.quote(options.name)}`); + if (isRegExp2(options.description)) + attrs.push(`description: ${this.regexToSourceString(options.description)}`); + else if (typeof options.description === "string") + attrs.push(`description: ${this.quote(options.description)}`); + if (options.exact && (typeof options.name === "string" || typeof options.description === "string")) + attrs.push(`exact: true`); + for (const { name, value: value2 } of options.attrs) + attrs.push(`${name}: ${typeof value2 === "string" ? this.quote(value2) : value2}`); + const attrString = attrs.length ? `, { ${attrs.join(", ")} }` : ""; + return `getByRole(${this.quote(body)}${attrString})`; + case "has-text": + return `filter({ hasText: ${this.toHasText(body)} })`; + case "has-not-text": + return `filter({ hasNotText: ${this.toHasText(body)} })`; + case "has": + return `filter({ has: ${body} })`; + case "hasNot": + return `filter({ hasNot: ${body} })`; + case "and": + return `and(${body})`; + case "or": + return `or(${body})`; + case "chain": + return `locator(${body})`; + case "test-id": + return `getByTestId(${this.toTestIdValue(body)})`; + case "text": + return this.toCallWithExact("getByText", body, !!options.exact); + case "alt": + return this.toCallWithExact("getByAltText", body, !!options.exact); + case "placeholder": + return this.toCallWithExact("getByPlaceholder", body, !!options.exact); + case "label": + return this.toCallWithExact("getByLabel", body, !!options.exact); + case "title": + return this.toCallWithExact("getByTitle", body, !!options.exact); + default: + throw new Error("Unknown selector kind " + kind); + } + } + chainLocators(locators) { + return locators.join("."); + } + regexToSourceString(re2) { + return normalizeEscapedRegexQuotes(String(re2)); + } + toCallWithExact(method, body, exact) { + if (isRegExp2(body)) + return `${method}(${this.regexToSourceString(body)})`; + return exact ? `${method}(${this.quote(body)}, { exact: true })` : `${method}(${this.quote(body)})`; + } + toHasText(body) { + if (isRegExp2(body)) + return this.regexToSourceString(body); + return this.quote(body); + } + toTestIdValue(value2) { + if (isRegExp2(value2)) + return this.regexToSourceString(value2); + return this.quote(value2); + } + quote(text2) { + return escapeWithQuotes(text2, this.preferredQuote ?? "'"); + } + }; + PythonLocatorFactory = class { + generateLocator(base, kind, body, options = {}) { + switch (kind) { + case "default": + if (options.hasText !== void 0) + return `locator(${this.quote(body)}, has_text=${this.toHasText(options.hasText)})`; + if (options.hasNotText !== void 0) + return `locator(${this.quote(body)}, has_not_text=${this.toHasText(options.hasNotText)})`; + return `locator(${this.quote(body)})`; + case "frame-locator": + return `frame_locator(${this.quote(body)})`; + case "frame": + return `content_frame`; + case "nth": + return `nth(${body})`; + case "first": + return `first`; + case "last": + return `last`; + case "visible": + return `filter(visible=${body === "true" ? "True" : "False"})`; + case "role": + const attrs = []; + if (isRegExp2(options.name)) + attrs.push(`name=${this.regexToString(options.name)}`); + else if (typeof options.name === "string") + attrs.push(`name=${this.quote(options.name)}`); + if (isRegExp2(options.description)) + attrs.push(`description=${this.regexToString(options.description)}`); + else if (typeof options.description === "string") + attrs.push(`description=${this.quote(options.description)}`); + if (options.exact && (typeof options.name === "string" || typeof options.description === "string")) + attrs.push(`exact=True`); + for (const { name, value: value2 } of options.attrs) { + let valueString = typeof value2 === "string" ? this.quote(value2) : value2; + if (typeof value2 === "boolean") + valueString = value2 ? "True" : "False"; + attrs.push(`${toSnakeCase(name)}=${valueString}`); + } + const attrString = attrs.length ? `, ${attrs.join(", ")}` : ""; + return `get_by_role(${this.quote(body)}${attrString})`; + case "has-text": + return `filter(has_text=${this.toHasText(body)})`; + case "has-not-text": + return `filter(has_not_text=${this.toHasText(body)})`; + case "has": + return `filter(has=${body})`; + case "hasNot": + return `filter(has_not=${body})`; + case "and": + return `and_(${body})`; + case "or": + return `or_(${body})`; + case "chain": + return `locator(${body})`; + case "test-id": + return `get_by_test_id(${this.toTestIdValue(body)})`; + case "text": + return this.toCallWithExact("get_by_text", body, !!options.exact); + case "alt": + return this.toCallWithExact("get_by_alt_text", body, !!options.exact); + case "placeholder": + return this.toCallWithExact("get_by_placeholder", body, !!options.exact); + case "label": + return this.toCallWithExact("get_by_label", body, !!options.exact); + case "title": + return this.toCallWithExact("get_by_title", body, !!options.exact); + default: + throw new Error("Unknown selector kind " + kind); + } + } + chainLocators(locators) { + return locators.join("."); + } + regexToString(body) { + const suffix = body.flags.includes("i") ? ", re.IGNORECASE" : ""; + return `re.compile(r"${normalizeEscapedRegexQuotes(body.source).replace(/\\\//, "/").replace(/"/g, '\\"')}"${suffix})`; + } + toCallWithExact(method, body, exact) { + if (isRegExp2(body)) + return `${method}(${this.regexToString(body)})`; + if (exact) + return `${method}(${this.quote(body)}, exact=True)`; + return `${method}(${this.quote(body)})`; + } + toHasText(body) { + if (isRegExp2(body)) + return this.regexToString(body); + return `${this.quote(body)}`; + } + toTestIdValue(value2) { + if (isRegExp2(value2)) + return this.regexToString(value2); + return this.quote(value2); + } + quote(text2) { + return escapeWithQuotes(text2, '"'); + } + }; + JavaLocatorFactory = class { + generateLocator(base, kind, body, options = {}) { + let clazz; + switch (base) { + case "page": + clazz = "Page"; + break; + case "frame-locator": + clazz = "FrameLocator"; + break; + case "locator": + clazz = "Locator"; + break; + } + switch (kind) { + case "default": + if (options.hasText !== void 0) + return `locator(${this.quote(body)}, new ${clazz}.LocatorOptions().setHasText(${this.toHasText(options.hasText)}))`; + if (options.hasNotText !== void 0) + return `locator(${this.quote(body)}, new ${clazz}.LocatorOptions().setHasNotText(${this.toHasText(options.hasNotText)}))`; + return `locator(${this.quote(body)})`; + case "frame-locator": + return `frameLocator(${this.quote(body)})`; + case "frame": + return `contentFrame()`; + case "nth": + return `nth(${body})`; + case "first": + return `first()`; + case "last": + return `last()`; + case "visible": + return `filter(new ${clazz}.FilterOptions().setVisible(${body === "true" ? "true" : "false"}))`; + case "role": + const attrs = []; + if (isRegExp2(options.name)) + attrs.push(`.setName(${this.regexToString(options.name)})`); + else if (typeof options.name === "string") + attrs.push(`.setName(${this.quote(options.name)})`); + if (isRegExp2(options.description)) + attrs.push(`.setDescription(${this.regexToString(options.description)})`); + else if (typeof options.description === "string") + attrs.push(`.setDescription(${this.quote(options.description)})`); + if (options.exact && (typeof options.name === "string" || typeof options.description === "string")) + attrs.push(`.setExact(true)`); + for (const { name, value: value2 } of options.attrs) + attrs.push(`.set${toTitleCase(name)}(${typeof value2 === "string" ? this.quote(value2) : value2})`); + const attrString = attrs.length ? `, new ${clazz}.GetByRoleOptions()${attrs.join("")}` : ""; + return `getByRole(AriaRole.${toSnakeCase(body).toUpperCase()}${attrString})`; + case "has-text": + return `filter(new ${clazz}.FilterOptions().setHasText(${this.toHasText(body)}))`; + case "has-not-text": + return `filter(new ${clazz}.FilterOptions().setHasNotText(${this.toHasText(body)}))`; + case "has": + return `filter(new ${clazz}.FilterOptions().setHas(${body}))`; + case "hasNot": + return `filter(new ${clazz}.FilterOptions().setHasNot(${body}))`; + case "and": + return `and(${body})`; + case "or": + return `or(${body})`; + case "chain": + return `locator(${body})`; + case "test-id": + return `getByTestId(${this.toTestIdValue(body)})`; + case "text": + return this.toCallWithExact(clazz, "getByText", body, !!options.exact); + case "alt": + return this.toCallWithExact(clazz, "getByAltText", body, !!options.exact); + case "placeholder": + return this.toCallWithExact(clazz, "getByPlaceholder", body, !!options.exact); + case "label": + return this.toCallWithExact(clazz, "getByLabel", body, !!options.exact); + case "title": + return this.toCallWithExact(clazz, "getByTitle", body, !!options.exact); + default: + throw new Error("Unknown selector kind " + kind); + } + } + chainLocators(locators) { + return locators.join("."); + } + regexToString(body) { + const suffix = body.flags.includes("i") ? ", Pattern.CASE_INSENSITIVE" : ""; + return `Pattern.compile(${this.quote(normalizeEscapedRegexQuotes(body.source))}${suffix})`; + } + toCallWithExact(clazz, method, body, exact) { + if (isRegExp2(body)) + return `${method}(${this.regexToString(body)})`; + if (exact) + return `${method}(${this.quote(body)}, new ${clazz}.${toTitleCase(method)}Options().setExact(true))`; + return `${method}(${this.quote(body)})`; + } + toHasText(body) { + if (isRegExp2(body)) + return this.regexToString(body); + return this.quote(body); + } + toTestIdValue(value2) { + if (isRegExp2(value2)) + return this.regexToString(value2); + return this.quote(value2); + } + quote(text2) { + return escapeWithQuotes(text2, '"'); + } + }; + CSharpLocatorFactory = class { + generateLocator(base, kind, body, options = {}) { + switch (kind) { + case "default": + if (options.hasText !== void 0) + return `Locator(${this.quote(body)}, new() { ${this.toHasText(options.hasText)} })`; + if (options.hasNotText !== void 0) + return `Locator(${this.quote(body)}, new() { ${this.toHasNotText(options.hasNotText)} })`; + return `Locator(${this.quote(body)})`; + case "frame-locator": + return `FrameLocator(${this.quote(body)})`; + case "frame": + return `ContentFrame`; + case "nth": + return `Nth(${body})`; + case "first": + return `First`; + case "last": + return `Last`; + case "visible": + return `Filter(new() { Visible = ${body === "true" ? "true" : "false"} })`; + case "role": + const attrs = []; + if (isRegExp2(options.name)) + attrs.push(`NameRegex = ${this.regexToString(options.name)}`); + else if (typeof options.name === "string") + attrs.push(`Name = ${this.quote(options.name)}`); + if (isRegExp2(options.description)) + attrs.push(`DescriptionRegex = ${this.regexToString(options.description)}`); + else if (typeof options.description === "string") + attrs.push(`Description = ${this.quote(options.description)}`); + if (options.exact && (typeof options.name === "string" || typeof options.description === "string")) + attrs.push(`Exact = true`); + for (const { name, value: value2 } of options.attrs) + attrs.push(`${toTitleCase(name)} = ${typeof value2 === "string" ? this.quote(value2) : value2}`); + const attrString = attrs.length ? `, new() { ${attrs.join(", ")} }` : ""; + return `GetByRole(AriaRole.${toTitleCase(body)}${attrString})`; + case "has-text": + return `Filter(new() { ${this.toHasText(body)} })`; + case "has-not-text": + return `Filter(new() { ${this.toHasNotText(body)} })`; + case "has": + return `Filter(new() { Has = ${body} })`; + case "hasNot": + return `Filter(new() { HasNot = ${body} })`; + case "and": + return `And(${body})`; + case "or": + return `Or(${body})`; + case "chain": + return `Locator(${body})`; + case "test-id": + return `GetByTestId(${this.toTestIdValue(body)})`; + case "text": + return this.toCallWithExact("GetByText", body, !!options.exact); + case "alt": + return this.toCallWithExact("GetByAltText", body, !!options.exact); + case "placeholder": + return this.toCallWithExact("GetByPlaceholder", body, !!options.exact); + case "label": + return this.toCallWithExact("GetByLabel", body, !!options.exact); + case "title": + return this.toCallWithExact("GetByTitle", body, !!options.exact); + default: + throw new Error("Unknown selector kind " + kind); + } + } + chainLocators(locators) { + return locators.join("."); + } + regexToString(body) { + const suffix = body.flags.includes("i") ? ", RegexOptions.IgnoreCase" : ""; + return `new Regex(${this.quote(normalizeEscapedRegexQuotes(body.source))}${suffix})`; + } + toCallWithExact(method, body, exact) { + if (isRegExp2(body)) + return `${method}(${this.regexToString(body)})`; + if (exact) + return `${method}(${this.quote(body)}, new() { Exact = true })`; + return `${method}(${this.quote(body)})`; + } + toHasText(body) { + if (isRegExp2(body)) + return `HasTextRegex = ${this.regexToString(body)}`; + return `HasText = ${this.quote(body)}`; + } + toTestIdValue(value2) { + if (isRegExp2(value2)) + return this.regexToString(value2); + return this.quote(value2); + } + toHasNotText(body) { + if (isRegExp2(body)) + return `HasNotTextRegex = ${this.regexToString(body)}`; + return `HasNotText = ${this.quote(body)}`; + } + quote(text2) { + return escapeWithQuotes(text2, '"'); + } + }; + JsonlLocatorFactory = class { + generateLocator(base, kind, body, options = {}) { + return JSON.stringify({ + kind, + body, + options + }); + } + chainLocators(locators) { + const objects = locators.map((l) => JSON.parse(l)); + for (let i = 0; i < objects.length - 1; ++i) + objects[i].next = objects[i + 1]; + return JSON.stringify(objects[0]); + } + }; + generators = { + javascript: JavaScriptLocatorFactory, + python: PythonLocatorFactory, + java: JavaLocatorFactory, + csharp: CSharpLocatorFactory, + jsonl: JsonlLocatorFactory + }; + } +}); + +// packages/isomorphic/stackTrace.ts +function captureRawStack() { + const stackTraceLimit = Error.stackTraceLimit; + Error.stackTraceLimit = 50; + const error = new Error(); + const stack = error.stack || ""; + Error.stackTraceLimit = stackTraceLimit; + return stack.split("\n"); +} +function parseStackFrame(text2, pathSeparator, showInternalStackFrames) { + const match = text2 && text2.match(re); + if (!match) + return null; + let fname = match[2]; + let file = match[7]; + if (!file) + return null; + if (!showInternalStackFrames && (file.startsWith("internal") || file.startsWith("node:"))) + return null; + const line = match[8]; + const column = match[9]; + const closeParen = match[11] === ")"; + const frame = { + file: "", + line: 0, + column: 0 + }; + if (line) + frame.line = Number(line); + if (column) + frame.column = Number(column); + if (closeParen && file) { + let closes = 0; + for (let i = file.length - 1; i > 0; i--) { + if (file.charAt(i) === ")") { + closes++; + } else if (file.charAt(i) === "(" && file.charAt(i - 1) === " ") { + closes--; + if (closes === -1 && file.charAt(i - 1) === " ") { + const before = file.slice(0, i - 1); + const after = file.slice(i + 1); + file = after; + fname += ` (${before}`; + break; + } + } + } + } + if (fname) { + const methodMatch = fname.match(methodRe); + if (methodMatch) + fname = methodMatch[1]; + } + if (file) { + if (file.startsWith("file://")) + file = fileURLToPath(file, pathSeparator); + frame.file = file; + } + if (fname) + frame.function = fname; + return frame; +} +function rewriteErrorMessage(e, newMessage) { + const lines = (e.stack?.split("\n") || []).filter((l) => l.startsWith(" at ")); + e.message = newMessage; + const errorTitle = `${e.name}: ${e.message}`; + if (lines.length) + e.stack = `${errorTitle} +${lines.join("\n")}`; + return e; +} +function stringifyStackFrames(frames) { + const stackLines = []; + for (const frame of frames) { + if (frame.function) + stackLines.push(` at ${frame.function} (${frame.file}:${frame.line}:${frame.column})`); + else + stackLines.push(` at ${frame.file}:${frame.line}:${frame.column}`); + } + return stackLines; +} +function splitErrorMessage(message) { + const separationIdx = message.indexOf(":"); + return { + name: separationIdx !== -1 ? message.slice(0, separationIdx) : "", + message: separationIdx !== -1 && separationIdx + 2 <= message.length ? message.substring(separationIdx + 2) : message + }; +} +function parseErrorStack(stack, pathSeparator, showInternalStackFrames = false) { + const lines = stack.split("\n"); + let firstStackLine = lines.findIndex((line) => line.startsWith(" at ")); + if (firstStackLine === -1) + firstStackLine = lines.length; + const message = lines.slice(0, firstStackLine).join("\n"); + const stackLines = lines.slice(firstStackLine); + let location2; + for (const line of stackLines) { + const frame = parseStackFrame(line, pathSeparator, showInternalStackFrames); + if (!frame || !frame.file) + continue; + if (belongsToNodeModules(frame.file, pathSeparator)) + continue; + location2 = { file: frame.file, column: frame.column || 0, line: frame.line || 0 }; + break; + } + return { message, stackLines, location: location2 }; +} +function belongsToNodeModules(file, pathSeparator) { + return file.includes(`${pathSeparator}node_modules${pathSeparator}`); +} +function fileURLToPath(fileUrl, pathSeparator) { + if (!fileUrl.startsWith("file://")) + return fileUrl; + let path59 = decodeURIComponent(fileUrl.slice(7)); + if (path59.startsWith("/") && /^[a-zA-Z]:/.test(path59.slice(1))) + path59 = path59.slice(1); + return path59.replace(/\//g, pathSeparator); +} +var re, methodRe; +var init_stackTrace = __esm({ + "packages/isomorphic/stackTrace.ts"() { + "use strict"; + re = new RegExp( + "^(?:\\s*at )?(?:(new) )?(?:(.*?) \\()?(?:eval at ([^ ]+) \\((.+?):(\\d+):(\\d+)\\), )?(?:(.+?):(\\d+):(\\d+)|(native))(\\)?)$" + ); + methodRe = /^(.*?) \[as (.*?)\]$/; + } +}); + +// packages/isomorphic/manualPromise.ts +function signalToPromise(signal) { + if (signal.aborted) + return { promise: Promise.resolve(), dispose: () => { + } }; + let dispose; + const promise = new Promise((resolve) => { + const onAbort = () => resolve(); + signal.addEventListener("abort", onAbort, { once: true }); + dispose = () => signal.removeEventListener("abort", onAbort); + }); + return { promise, dispose }; +} +function cloneError(error, frames) { + const clone = new Error(); + clone.name = error.name; + clone.message = error.message; + clone.stack = [error.name + ":" + error.message, ...frames].join("\n"); + return clone; +} +var ManualPromise, LongStandingScope; +var init_manualPromise = __esm({ + "packages/isomorphic/manualPromise.ts"() { + "use strict"; + init_stackTrace(); + ManualPromise = class extends Promise { + constructor() { + let resolve; + let reject; + super((f, r) => { + resolve = f; + reject = r; + }); + this._isDone = false; + this._resolve = resolve; + this._reject = reject; + } + isDone() { + return this._isDone; + } + resolve(t) { + this._isDone = true; + this._resolve(t); + } + reject(e) { + this._isDone = true; + this._reject(e); + } + static get [Symbol.species]() { + return Promise; + } + get [Symbol.toStringTag]() { + return "ManualPromise"; + } + }; + LongStandingScope = class { + constructor() { + this._terminatePromises = /* @__PURE__ */ new Map(); + this._isClosed = false; + } + reject(error) { + this._isClosed = true; + this._terminateError = error; + for (const p of this._terminatePromises.keys()) + p.resolve(error); + } + close(error) { + this._isClosed = true; + this._closeError = error; + for (const [p, frames] of this._terminatePromises) + p.resolve(cloneError(error, frames)); + } + isClosed() { + return this._isClosed; + } + static async raceMultiple(scopes, promise) { + return Promise.race(scopes.map((s) => s.race(promise))); + } + async race(promise) { + return this._race(Array.isArray(promise) ? promise : [promise], false); + } + async safeRace(promise, defaultValue) { + return this._race([promise], true, defaultValue); + } + async _race(promises, safe, defaultValue) { + const terminatePromise = new ManualPromise(); + const frames = captureRawStack(); + if (this._terminateError) + terminatePromise.resolve(this._terminateError); + if (this._closeError) + terminatePromise.resolve(cloneError(this._closeError, frames)); + this._terminatePromises.set(terminatePromise, frames); + try { + return await Promise.race([ + terminatePromise.then((e) => safe ? defaultValue : Promise.reject(e)), + ...promises + ]); + } finally { + this._terminatePromises.delete(terminatePromise); + } + } + }; + } +}); + +// packages/isomorphic/mimeType.ts +function isJsonMimeType(mimeType) { + return !!mimeType.match(/^(application\/json|application\/.*?\+json|text\/(x-)?json)(;\s*charset=.*)?$/); +} +function isXmlMimeType(mimeType) { + return !!mimeType.match(/^(application\/xml|application\/.*?\+xml|text\/xml)(;\s*charset=.*)?$/); +} +function isTextualMimeType(mimeType) { + return !!mimeType.match(/^(text\/.*?|application\/(json|(x-)?javascript|xml.*?|ecmascript|graphql|x-www-form-urlencoded)|image\/svg(\+xml)?|application\/.*?(\+json|\+xml))(;\s*charset=.*)?$/); +} +function getMimeTypeForPath(path59) { + const dotIndex = path59.lastIndexOf("."); + if (dotIndex === -1) + return null; + const extension = path59.substring(dotIndex + 1); + return types.get(extension) || null; +} +function getExtensionForMimeType(contentType) { + const subtype = (contentType ?? "").split(";")[0].split("/")[1]?.trim().toLowerCase() ?? ""; + if (!subtype) + return "bin"; + const tail = subtype.includes("+") ? subtype.split("+").pop() : subtype; + if (tail === "plain") + return "txt"; + if (tail === "javascript" || tail === "ecmascript") + return "js"; + if (tail === "jpeg") + return "jpg"; + return tail.replace(/[^a-z0-9]/g, "") || "bin"; +} +var types; +var init_mimeType = __esm({ + "packages/isomorphic/mimeType.ts"() { + "use strict"; + types = /* @__PURE__ */ new Map([ + ["ez", "application/andrew-inset"], + ["aw", "application/applixware"], + ["atom", "application/atom+xml"], + ["atomcat", "application/atomcat+xml"], + ["atomdeleted", "application/atomdeleted+xml"], + ["atomsvc", "application/atomsvc+xml"], + ["dwd", "application/atsc-dwd+xml"], + ["held", "application/atsc-held+xml"], + ["rsat", "application/atsc-rsat+xml"], + ["bdoc", "application/bdoc"], + ["xcs", "application/calendar+xml"], + ["ccxml", "application/ccxml+xml"], + ["cdfx", "application/cdfx+xml"], + ["cdmia", "application/cdmi-capability"], + ["cdmic", "application/cdmi-container"], + ["cdmid", "application/cdmi-domain"], + ["cdmio", "application/cdmi-object"], + ["cdmiq", "application/cdmi-queue"], + ["cu", "application/cu-seeme"], + ["mpd", "application/dash+xml"], + ["davmount", "application/davmount+xml"], + ["dbk", "application/docbook+xml"], + ["dssc", "application/dssc+der"], + ["xdssc", "application/dssc+xml"], + ["ecma", "application/ecmascript"], + ["es", "application/ecmascript"], + ["emma", "application/emma+xml"], + ["emotionml", "application/emotionml+xml"], + ["epub", "application/epub+zip"], + ["exi", "application/exi"], + ["exp", "application/express"], + ["fdt", "application/fdt+xml"], + ["pfr", "application/font-tdpfr"], + ["geojson", "application/geo+json"], + ["gml", "application/gml+xml"], + ["gpx", "application/gpx+xml"], + ["gxf", "application/gxf"], + ["gz", "application/gzip"], + ["hjson", "application/hjson"], + ["stk", "application/hyperstudio"], + ["ink", "application/inkml+xml"], + ["inkml", "application/inkml+xml"], + ["ipfix", "application/ipfix"], + ["its", "application/its+xml"], + ["ear", "application/java-archive"], + ["jar", "application/java-archive"], + ["war", "application/java-archive"], + ["ser", "application/java-serialized-object"], + ["class", "application/java-vm"], + ["js", "application/javascript"], + ["mjs", "application/javascript"], + ["json", "application/json"], + ["map", "application/json"], + ["json5", "application/json5"], + ["jsonml", "application/jsonml+json"], + ["jsonld", "application/ld+json"], + ["lgr", "application/lgr+xml"], + ["lostxml", "application/lost+xml"], + ["hqx", "application/mac-binhex40"], + ["cpt", "application/mac-compactpro"], + ["mads", "application/mads+xml"], + ["webmanifest", "application/manifest+json"], + ["mrc", "application/marc"], + ["mrcx", "application/marcxml+xml"], + ["ma", "application/mathematica"], + ["mb", "application/mathematica"], + ["nb", "application/mathematica"], + ["mathml", "application/mathml+xml"], + ["mbox", "application/mbox"], + ["mscml", "application/mediaservercontrol+xml"], + ["metalink", "application/metalink+xml"], + ["meta4", "application/metalink4+xml"], + ["mets", "application/mets+xml"], + ["maei", "application/mmt-aei+xml"], + ["musd", "application/mmt-usd+xml"], + ["mods", "application/mods+xml"], + ["m21", "application/mp21"], + ["mp21", "application/mp21"], + ["m4p", "application/mp4"], + ["mp4s", "application/mp4"], + ["doc", "application/msword"], + ["dot", "application/msword"], + ["mxf", "application/mxf"], + ["nq", "application/n-quads"], + ["nt", "application/n-triples"], + ["cjs", "application/node"], + ["bin", "application/octet-stream"], + ["bpk", "application/octet-stream"], + ["buffer", "application/octet-stream"], + ["deb", "application/octet-stream"], + ["deploy", "application/octet-stream"], + ["dist", "application/octet-stream"], + ["distz", "application/octet-stream"], + ["dll", "application/octet-stream"], + ["dmg", "application/octet-stream"], + ["dms", "application/octet-stream"], + ["dump", "application/octet-stream"], + ["elc", "application/octet-stream"], + ["exe", "application/octet-stream"], + ["img", "application/octet-stream"], + ["iso", "application/octet-stream"], + ["lrf", "application/octet-stream"], + ["mar", "application/octet-stream"], + ["msi", "application/octet-stream"], + ["msm", "application/octet-stream"], + ["msp", "application/octet-stream"], + ["pkg", "application/octet-stream"], + ["so", "application/octet-stream"], + ["oda", "application/oda"], + ["opf", "application/oebps-package+xml"], + ["ogx", "application/ogg"], + ["omdoc", "application/omdoc+xml"], + ["onepkg", "application/onenote"], + ["onetmp", "application/onenote"], + ["onetoc", "application/onenote"], + ["onetoc2", "application/onenote"], + ["oxps", "application/oxps"], + ["relo", "application/p2p-overlay+xml"], + ["xer", "application/patch-ops-error+xml"], + ["pdf", "application/pdf"], + ["pgp", "application/pgp-encrypted"], + ["asc", "application/pgp-signature"], + ["sig", "application/pgp-signature"], + ["prf", "application/pics-rules"], + ["p10", "application/pkcs10"], + ["p7c", "application/pkcs7-mime"], + ["p7m", "application/pkcs7-mime"], + ["p7s", "application/pkcs7-signature"], + ["p8", "application/pkcs8"], + ["ac", "application/pkix-attr-cert"], + ["cer", "application/pkix-cert"], + ["crl", "application/pkix-crl"], + ["pkipath", "application/pkix-pkipath"], + ["pki", "application/pkixcmp"], + ["pls", "application/pls+xml"], + ["ai", "application/postscript"], + ["eps", "application/postscript"], + ["ps", "application/postscript"], + ["provx", "application/provenance+xml"], + ["pskcxml", "application/pskc+xml"], + ["raml", "application/raml+yaml"], + ["owl", "application/rdf+xml"], + ["rdf", "application/rdf+xml"], + ["rif", "application/reginfo+xml"], + ["rnc", "application/relax-ng-compact-syntax"], + ["rl", "application/resource-lists+xml"], + ["rld", "application/resource-lists-diff+xml"], + ["rs", "application/rls-services+xml"], + ["rapd", "application/route-apd+xml"], + ["sls", "application/route-s-tsid+xml"], + ["rusd", "application/route-usd+xml"], + ["gbr", "application/rpki-ghostbusters"], + ["mft", "application/rpki-manifest"], + ["roa", "application/rpki-roa"], + ["rsd", "application/rsd+xml"], + ["rss", "application/rss+xml"], + ["rtf", "application/rtf"], + ["sbml", "application/sbml+xml"], + ["scq", "application/scvp-cv-request"], + ["scs", "application/scvp-cv-response"], + ["spq", "application/scvp-vp-request"], + ["spp", "application/scvp-vp-response"], + ["sdp", "application/sdp"], + ["senmlx", "application/senml+xml"], + ["sensmlx", "application/sensml+xml"], + ["setpay", "application/set-payment-initiation"], + ["setreg", "application/set-registration-initiation"], + ["shf", "application/shf+xml"], + ["sieve", "application/sieve"], + ["siv", "application/sieve"], + ["smi", "application/smil+xml"], + ["smil", "application/smil+xml"], + ["rq", "application/sparql-query"], + ["srx", "application/sparql-results+xml"], + ["gram", "application/srgs"], + ["grxml", "application/srgs+xml"], + ["sru", "application/sru+xml"], + ["ssdl", "application/ssdl+xml"], + ["ssml", "application/ssml+xml"], + ["swidtag", "application/swid+xml"], + ["tei", "application/tei+xml"], + ["teicorpus", "application/tei+xml"], + ["tfi", "application/thraud+xml"], + ["tsd", "application/timestamped-data"], + ["toml", "application/toml"], + ["trig", "application/trig"], + ["ttml", "application/ttml+xml"], + ["ubj", "application/ubjson"], + ["rsheet", "application/urc-ressheet+xml"], + ["td", "application/urc-targetdesc+xml"], + ["vxml", "application/voicexml+xml"], + ["wasm", "application/wasm"], + ["wgt", "application/widget"], + ["hlp", "application/winhlp"], + ["wsdl", "application/wsdl+xml"], + ["wspolicy", "application/wspolicy+xml"], + ["xaml", "application/xaml+xml"], + ["xav", "application/xcap-att+xml"], + ["xca", "application/xcap-caps+xml"], + ["xdf", "application/xcap-diff+xml"], + ["xel", "application/xcap-el+xml"], + ["xns", "application/xcap-ns+xml"], + ["xenc", "application/xenc+xml"], + ["xht", "application/xhtml+xml"], + ["xhtml", "application/xhtml+xml"], + ["xlf", "application/xliff+xml"], + ["rng", "application/xml"], + ["xml", "application/xml"], + ["xsd", "application/xml"], + ["xsl", "application/xml"], + ["dtd", "application/xml-dtd"], + ["xop", "application/xop+xml"], + ["xpl", "application/xproc+xml"], + ["*xsl", "application/xslt+xml"], + ["xslt", "application/xslt+xml"], + ["xspf", "application/xspf+xml"], + ["mxml", "application/xv+xml"], + ["xhvml", "application/xv+xml"], + ["xvm", "application/xv+xml"], + ["xvml", "application/xv+xml"], + ["yang", "application/yang"], + ["yin", "application/yin+xml"], + ["zip", "application/zip"], + ["*3gpp", "audio/3gpp"], + ["adp", "audio/adpcm"], + ["amr", "audio/amr"], + ["au", "audio/basic"], + ["snd", "audio/basic"], + ["kar", "audio/midi"], + ["mid", "audio/midi"], + ["midi", "audio/midi"], + ["rmi", "audio/midi"], + ["mxmf", "audio/mobile-xmf"], + ["*mp3", "audio/mp3"], + ["m4a", "audio/mp4"], + ["mp4a", "audio/mp4"], + ["m2a", "audio/mpeg"], + ["m3a", "audio/mpeg"], + ["mp2", "audio/mpeg"], + ["mp2a", "audio/mpeg"], + ["mp3", "audio/mpeg"], + ["mpga", "audio/mpeg"], + ["oga", "audio/ogg"], + ["ogg", "audio/ogg"], + ["opus", "audio/ogg"], + ["spx", "audio/ogg"], + ["s3m", "audio/s3m"], + ["sil", "audio/silk"], + ["wav", "audio/wav"], + ["*wav", "audio/wave"], + ["weba", "audio/webm"], + ["xm", "audio/xm"], + ["ttc", "font/collection"], + ["otf", "font/otf"], + ["ttf", "font/ttf"], + ["woff", "font/woff"], + ["woff2", "font/woff2"], + ["exr", "image/aces"], + ["apng", "image/apng"], + ["avif", "image/avif"], + ["bmp", "image/bmp"], + ["cgm", "image/cgm"], + ["drle", "image/dicom-rle"], + ["emf", "image/emf"], + ["fits", "image/fits"], + ["g3", "image/g3fax"], + ["gif", "image/gif"], + ["heic", "image/heic"], + ["heics", "image/heic-sequence"], + ["heif", "image/heif"], + ["heifs", "image/heif-sequence"], + ["hej2", "image/hej2k"], + ["hsj2", "image/hsj2"], + ["ief", "image/ief"], + ["jls", "image/jls"], + ["jp2", "image/jp2"], + ["jpg2", "image/jp2"], + ["jpe", "image/jpeg"], + ["jpeg", "image/jpeg"], + ["jpg", "image/jpeg"], + ["jph", "image/jph"], + ["jhc", "image/jphc"], + ["jpm", "image/jpm"], + ["jpf", "image/jpx"], + ["jpx", "image/jpx"], + ["jxr", "image/jxr"], + ["jxra", "image/jxra"], + ["jxrs", "image/jxrs"], + ["jxs", "image/jxs"], + ["jxsc", "image/jxsc"], + ["jxsi", "image/jxsi"], + ["jxss", "image/jxss"], + ["ktx", "image/ktx"], + ["ktx2", "image/ktx2"], + ["png", "image/png"], + ["sgi", "image/sgi"], + ["svg", "image/svg+xml"], + ["svgz", "image/svg+xml"], + ["t38", "image/t38"], + ["tif", "image/tiff"], + ["tiff", "image/tiff"], + ["tfx", "image/tiff-fx"], + ["webp", "image/webp"], + ["wmf", "image/wmf"], + ["disposition-notification", "message/disposition-notification"], + ["u8msg", "message/global"], + ["u8dsn", "message/global-delivery-status"], + ["u8mdn", "message/global-disposition-notification"], + ["u8hdr", "message/global-headers"], + ["eml", "message/rfc822"], + ["mime", "message/rfc822"], + ["3mf", "model/3mf"], + ["gltf", "model/gltf+json"], + ["glb", "model/gltf-binary"], + ["iges", "model/iges"], + ["igs", "model/iges"], + ["mesh", "model/mesh"], + ["msh", "model/mesh"], + ["silo", "model/mesh"], + ["mtl", "model/mtl"], + ["obj", "model/obj"], + ["stpx", "model/step+xml"], + ["stpz", "model/step+zip"], + ["stpxz", "model/step-xml+zip"], + ["stl", "model/stl"], + ["vrml", "model/vrml"], + ["wrl", "model/vrml"], + ["*x3db", "model/x3d+binary"], + ["x3dbz", "model/x3d+binary"], + ["x3db", "model/x3d+fastinfoset"], + ["*x3dv", "model/x3d+vrml"], + ["x3dvz", "model/x3d+vrml"], + ["x3d", "model/x3d+xml"], + ["x3dz", "model/x3d+xml"], + ["x3dv", "model/x3d-vrml"], + ["appcache", "text/cache-manifest"], + ["manifest", "text/cache-manifest"], + ["ics", "text/calendar"], + ["ifb", "text/calendar"], + ["coffee", "text/coffeescript"], + ["litcoffee", "text/coffeescript"], + ["css", "text/css"], + ["csv", "text/csv"], + ["htm", "text/html"], + ["html", "text/html"], + ["shtml", "text/html"], + ["jade", "text/jade"], + ["jsx", "text/jsx"], + ["less", "text/less"], + ["markdown", "text/markdown"], + ["md", "text/markdown"], + ["mml", "text/mathml"], + ["mdx", "text/mdx"], + ["n3", "text/n3"], + ["conf", "text/plain"], + ["def", "text/plain"], + ["in", "text/plain"], + ["ini", "text/plain"], + ["list", "text/plain"], + ["log", "text/plain"], + ["text", "text/plain"], + ["txt", "text/plain"], + ["rtx", "text/richtext"], + ["*rtf", "text/rtf"], + ["sgm", "text/sgml"], + ["sgml", "text/sgml"], + ["shex", "text/shex"], + ["slim", "text/slim"], + ["slm", "text/slim"], + ["spdx", "text/spdx"], + ["styl", "text/stylus"], + ["stylus", "text/stylus"], + ["tsv", "text/tab-separated-values"], + ["man", "text/troff"], + ["me", "text/troff"], + ["ms", "text/troff"], + ["roff", "text/troff"], + ["t", "text/troff"], + ["tr", "text/troff"], + ["ttl", "text/turtle"], + ["uri", "text/uri-list"], + ["uris", "text/uri-list"], + ["urls", "text/uri-list"], + ["vcard", "text/vcard"], + ["vtt", "text/vtt"], + ["*xml", "text/xml"], + ["yaml", "text/yaml"], + ["yml", "text/yaml"], + ["3gp", "video/3gpp"], + ["3gpp", "video/3gpp"], + ["3g2", "video/3gpp2"], + ["h261", "video/h261"], + ["h263", "video/h263"], + ["h264", "video/h264"], + ["m4s", "video/iso.segment"], + ["jpgv", "video/jpeg"], + ["jpm", "video/jpm"], + ["jpgm", "video/jpm"], + ["mj2", "video/mj2"], + ["mjp2", "video/mj2"], + ["ts", "application/typescript"], + ["mp4", "video/mp4"], + ["mp4v", "video/mp4"], + ["mpg4", "video/mp4"], + ["m1v", "video/mpeg"], + ["m2v", "video/mpeg"], + ["mpe", "video/mpeg"], + ["mpeg", "video/mpeg"], + ["mpg", "video/mpeg"], + ["ogv", "video/ogg"], + ["mov", "video/quicktime"], + ["qt", "video/quicktime"], + ["webm", "video/webm"] + ]); + } +}); + +// packages/isomorphic/multimap.ts +var MultiMap; +var init_multimap = __esm({ + "packages/isomorphic/multimap.ts"() { + "use strict"; + MultiMap = class { + constructor() { + this._map = /* @__PURE__ */ new Map(); + } + set(key, value2) { + let values = this._map.get(key); + if (!values) { + values = []; + this._map.set(key, values); + } + values.push(value2); + } + get(key) { + return this._map.get(key) || []; + } + has(key) { + return this._map.has(key); + } + delete(key, value2) { + const values = this._map.get(key); + if (!values) + return; + if (values.includes(value2)) + this._map.set(key, values.filter((v) => value2 !== v)); + } + deleteAll(key) { + this._map.delete(key); + } + hasValue(key, value2) { + const values = this._map.get(key); + if (!values) + return false; + return values.includes(value2); + } + get size() { + return this._map.size; + } + [Symbol.iterator]() { + return this._map[Symbol.iterator](); + } + keys() { + return this._map.keys(); + } + values() { + const result2 = []; + for (const key of this.keys()) + result2.push(...this.get(key)); + return result2; + } + clear() { + this._map.clear(); + } + }; + } +}); + +// packages/isomorphic/protocolMetainfo.ts +function getMetainfo(metadata) { + return methodMetainfo.get(metadata.type + "." + metadata.method); +} +var methodMetainfo; +var init_protocolMetainfo = __esm({ + "packages/isomorphic/protocolMetainfo.ts"() { + "use strict"; + methodMetainfo = /* @__PURE__ */ new Map([ + ["Android.devices", { internal: true }], + ["AndroidSocket.write", { internal: true }], + ["AndroidSocket.close", { internal: true }], + ["AndroidDevice.wait", { title: "Wait" }], + ["AndroidDevice.fill", { title: 'Fill "{text}"' }], + ["AndroidDevice.tap", { title: "Tap" }], + ["AndroidDevice.drag", { title: "Drag" }], + ["AndroidDevice.fling", { title: "Fling" }], + ["AndroidDevice.longTap", { title: "Long tap" }], + ["AndroidDevice.pinchClose", { title: "Pinch close" }], + ["AndroidDevice.pinchOpen", { title: "Pinch open" }], + ["AndroidDevice.scroll", { title: "Scroll" }], + ["AndroidDevice.swipe", { title: "Swipe" }], + ["AndroidDevice.info", { internal: true }], + ["AndroidDevice.screenshot", { title: "Screenshot" }], + ["AndroidDevice.inputType", { title: "Type" }], + ["AndroidDevice.inputPress", { title: "Press" }], + ["AndroidDevice.inputTap", { title: "Tap" }], + ["AndroidDevice.inputSwipe", { title: "Swipe" }], + ["AndroidDevice.inputDrag", { title: "Drag" }], + ["AndroidDevice.launchBrowser", { title: "Launch browser" }], + ["AndroidDevice.open", { title: "Open app" }], + ["AndroidDevice.shell", { title: "Execute shell command", group: "configuration" }], + ["AndroidDevice.installApk", { title: "Install apk" }], + ["AndroidDevice.push", { title: "Push" }], + ["AndroidDevice.connectToWebView", { title: "Connect to Web View" }], + ["AndroidDevice.close", { internal: true }], + ["APIRequestContext.fetch", { title: '{method} "{url}"' }], + ["APIRequestContext.fetchResponseBody", { title: "Get response body", group: "getter" }], + ["APIRequestContext.fetchLog", { internal: true }], + ["APIRequestContext.storageState", { title: "Get storage state", group: "configuration" }], + ["APIRequestContext.disposeAPIResponse", { internal: true }], + ["APIRequestContext.dispose", { internal: true, potentiallyClosesScope: true }], + ["Artifact.pathAfterFinished", { internal: true }], + ["Artifact.saveAs", { internal: true }], + ["Artifact.saveAsStream", { internal: true }], + ["Artifact.failure", { internal: true }], + ["Artifact.stream", { internal: true }], + ["Artifact.cancel", { internal: true }], + ["Artifact.delete", { internal: true, potentiallyClosesScope: true }], + ["Stream.read", { internal: true }], + ["Stream.close", { internal: true }], + ["WritableStream.write", { internal: true }], + ["WritableStream.close", { internal: true }], + ["Browser.startServer", { title: "Start server" }], + ["Browser.stopServer", { title: "Stop server" }], + ["Browser.close", { title: "Close browser", pause: true, potentiallyClosesScope: true }], + ["Browser.killForTests", { internal: true, potentiallyClosesScope: true }], + ["Browser.defaultUserAgentForTest", { internal: true }], + ["Browser.newContext", { title: "Create context" }], + ["Browser.newContextForReuse", { internal: true }], + ["Browser.disconnectFromReusedContext", { internal: true }], + ["Browser.newBrowserCDPSession", { title: "Create CDP session", group: "configuration" }], + ["Browser.startTracing", { title: "Start browser tracing", group: "configuration" }], + ["Browser.stopTracing", { title: "Stop browser tracing", group: "configuration" }], + ["BrowserContext.addCookies", { title: "Add cookies", group: "configuration" }], + ["BrowserContext.addInitScript", { title: "Add init script", group: "configuration" }], + ["BrowserContext.clearCookies", { title: "Clear cookies", group: "configuration" }], + ["BrowserContext.clearPermissions", { title: "Clear permissions", group: "configuration" }], + ["BrowserContext.close", { title: "Close context", pause: true, potentiallyClosesScope: true }], + ["BrowserContext.cookies", { title: "Get cookies", group: "getter" }], + ["BrowserContext.exposeBinding", { title: "Expose binding", group: "configuration" }], + ["BrowserContext.grantPermissions", { title: "Grant permissions", group: "configuration" }], + ["BrowserContext.newPage", { title: "Create page" }], + ["BrowserContext.registerSelectorEngine", { internal: true }], + ["BrowserContext.setTestIdAttributeName", { internal: true }], + ["BrowserContext.setExtraHTTPHeaders", { title: "Set extra HTTP headers", group: "configuration" }], + ["BrowserContext.setGeolocation", { title: "Set geolocation", group: "configuration" }], + ["BrowserContext.setHTTPCredentials", { title: "Set HTTP credentials", group: "configuration" }], + ["BrowserContext.setNetworkInterceptionPatterns", { title: "Route requests", group: "route" }], + ["BrowserContext.setWebSocketInterceptionPatterns", { title: "Route WebSockets", group: "route" }], + ["BrowserContext.setOffline", { title: "Set offline mode" }], + ["BrowserContext.storageState", { title: "Get storage state", group: "configuration" }], + ["BrowserContext.setStorageState", { title: "Set storage state", group: "configuration" }], + ["BrowserContext.pause", { title: "Pause" }], + ["BrowserContext.enableRecorder", { internal: true }], + ["BrowserContext.disableRecorder", { internal: true }], + ["BrowserContext.exposeConsoleApi", { internal: true }], + ["BrowserContext.newCDPSession", { title: "Create CDP session", group: "configuration" }], + ["BrowserContext.createTempFiles", { internal: true }], + ["BrowserContext.updateSubscription", { internal: true }], + ["BrowserContext.clockFastForward", { title: 'Fast forward clock "{ticksNumber|ticksString}"' }], + ["BrowserContext.clockInstall", { title: 'Install clock "{timeNumber|timeString}"' }], + ["BrowserContext.clockPauseAt", { title: 'Pause clock "{timeNumber|timeString}"' }], + ["BrowserContext.clockResume", { title: "Resume clock" }], + ["BrowserContext.clockRunFor", { title: 'Run clock "{ticksNumber|ticksString}"' }], + ["BrowserContext.clockSetFixedTime", { title: 'Set fixed time "{timeNumber|timeString}"' }], + ["BrowserContext.clockSetSystemTime", { title: 'Set system time "{timeNumber|timeString}"' }], + ["BrowserContext.credentialsInstall", { title: "Install virtual WebAuthn authenticator", group: "configuration" }], + ["BrowserContext.credentialsCreate", { title: 'Create virtual credential for "{rpId}"', group: "configuration" }], + ["BrowserContext.credentialsGet", { title: "Get virtual credentials", group: "configuration" }], + ["BrowserContext.credentialsDelete", { title: "Delete virtual credential", group: "configuration" }], + ["BrowserType.launch", { title: "Launch browser" }], + ["BrowserType.launchPersistentContext", { title: "Launch persistent context" }], + ["BrowserType.connectOverCDP", { title: "Connect over CDP" }], + ["BrowserType.connectToWorker", { title: "Connect to worker" }], + ["Disposable.dispose", { internal: true, potentiallyClosesScope: true }], + ["Electron.launch", { title: "Launch electron" }], + ["ElectronApplication.browserWindow", { internal: true }], + ["ElectronApplication.evaluateExpression", { title: "Evaluate" }], + ["ElectronApplication.evaluateExpressionHandle", { title: "Evaluate" }], + ["ElectronApplication.updateSubscription", { internal: true }], + ["Frame.evalOnSelector", { title: "Evaluate", snapshot: true, pause: true }], + ["Frame.evalOnSelectorAll", { title: "Evaluate", snapshot: true, pause: true }], + ["Frame.addScriptTag", { title: "Add script tag", snapshot: true, pause: true }], + ["Frame.addStyleTag", { title: "Add style tag", snapshot: true, pause: true }], + ["Frame.ariaSnapshot", { title: "Aria snapshot", group: "getter" }], + ["Frame.blur", { title: "Blur", slowMo: true, snapshot: true, pause: true }], + ["Frame.check", { title: "Check", slowMo: true, snapshot: true, pause: true, input: true, isAutoWaiting: true }], + ["Frame.click", { title: "Click", slowMo: true, snapshot: true, pause: true, input: true, isAutoWaiting: true, potentiallyClosesScope: true }], + ["Frame.content", { title: "Get content", snapshot: true, pause: true }], + ["Frame.dragAndDrop", { title: "Drag and drop", slowMo: true, snapshot: true, pause: true, input: true, isAutoWaiting: true }], + ["Frame.drop", { title: "Drop files or data onto an element", slowMo: true, snapshot: true, pause: true, input: true, isAutoWaiting: true }], + ["Frame.dblclick", { title: "Double click", slowMo: true, snapshot: true, pause: true, input: true, isAutoWaiting: true }], + ["Frame.dispatchEvent", { title: 'Dispatch "{type}"', slowMo: true, snapshot: true, pause: true }], + ["Frame.evaluateExpression", { title: "Evaluate", snapshot: true, pause: true }], + ["Frame.evaluateExpressionHandle", { title: "Evaluate", snapshot: true, pause: true }], + ["Frame.fill", { title: 'Fill "{value}"', slowMo: true, snapshot: true, pause: true, input: true, isAutoWaiting: true }], + ["Frame.focus", { title: "Focus", slowMo: true, snapshot: true, pause: true }], + ["Frame.frameElement", { title: "Get frame element", group: "getter" }], + ["Frame.resolveSelector", { internal: true }], + ["Frame.highlight", { internal: true }], + ["Frame.hideHighlight", { internal: true }], + ["Frame.getAttribute", { title: 'Get attribute "{name}"', snapshot: true, pause: true, group: "getter" }], + ["Frame.goto", { title: 'Navigate to "{url}"', slowMo: true, snapshot: true, pause: true }], + ["Frame.hover", { title: "Hover", slowMo: true, snapshot: true, pause: true, input: true, isAutoWaiting: true }], + ["Frame.innerHTML", { title: "Get HTML", snapshot: true, pause: true, group: "getter" }], + ["Frame.innerText", { title: "Get inner text", snapshot: true, pause: true, group: "getter" }], + ["Frame.inputValue", { title: "Get input value", snapshot: true, pause: true, group: "getter" }], + ["Frame.isChecked", { title: "Is checked", snapshot: true, pause: true, group: "getter" }], + ["Frame.isDisabled", { title: "Is disabled", snapshot: true, pause: true, group: "getter" }], + ["Frame.isEnabled", { title: "Is enabled", snapshot: true, pause: true, group: "getter" }], + ["Frame.isHidden", { title: "Is hidden", snapshot: true, pause: true, group: "getter" }], + ["Frame.isVisible", { title: "Is visible", snapshot: true, pause: true, group: "getter" }], + ["Frame.isEditable", { title: "Is editable", snapshot: true, pause: true, group: "getter" }], + ["Frame.press", { title: 'Press "{key}"', slowMo: true, snapshot: true, pause: true, input: true, isAutoWaiting: true }], + ["Frame.querySelector", { title: "Query selector", snapshot: true }], + ["Frame.querySelectorAll", { title: "Query selector all", snapshot: true }], + ["Frame.queryCount", { title: "Query count", snapshot: true, pause: true }], + ["Frame.selectOption", { title: "Select option", slowMo: true, snapshot: true, pause: true, input: true, isAutoWaiting: true }], + ["Frame.setContent", { title: "Set content", snapshot: true, pause: true }], + ["Frame.setInputFiles", { title: "Set input files", slowMo: true, snapshot: true, pause: true, input: true, isAutoWaiting: true }], + ["Frame.tap", { title: "Tap", slowMo: true, snapshot: true, pause: true, input: true, isAutoWaiting: true }], + ["Frame.textContent", { title: "Get text content", snapshot: true, pause: true, group: "getter" }], + ["Frame.title", { title: "Get page title", group: "getter" }], + ["Frame.type", { title: 'Type "{text}"', slowMo: true, snapshot: true, pause: true, input: true, isAutoWaiting: true }], + ["Frame.uncheck", { title: "Uncheck", slowMo: true, snapshot: true, pause: true, input: true, isAutoWaiting: true }], + ["Frame.waitForTimeout", { title: "Wait for timeout", snapshot: true }], + ["Frame.waitForFunction", { title: "Wait for function", snapshot: true, pause: true }], + ["Frame.waitForSelector", { title: "Wait for selector", snapshot: true }], + ["Frame.expect", { title: 'Expect "{expression}"', snapshot: true, pause: true }], + ["JSHandle.dispose", { internal: true, potentiallyClosesScope: true }], + ["ElementHandle.dispose", { internal: true, potentiallyClosesScope: true }], + ["JSHandle.evaluateExpression", { title: "Evaluate", snapshot: true, pause: true }], + ["ElementHandle.evaluateExpression", { title: "Evaluate", snapshot: true, pause: true }], + ["JSHandle.evaluateExpressionHandle", { title: "Evaluate", snapshot: true, pause: true }], + ["ElementHandle.evaluateExpressionHandle", { title: "Evaluate", snapshot: true, pause: true }], + ["JSHandle.getPropertyList", { title: "Get property list", group: "getter" }], + ["ElementHandle.getPropertyList", { title: "Get property list", group: "getter" }], + ["JSHandle.getProperty", { title: "Get JS property", group: "getter" }], + ["ElementHandle.getProperty", { title: "Get JS property", group: "getter" }], + ["JSHandle.jsonValue", { title: "Get JSON value", group: "getter" }], + ["ElementHandle.jsonValue", { title: "Get JSON value", group: "getter" }], + ["ElementHandle.evalOnSelector", { title: "Evaluate", snapshot: true, pause: true }], + ["ElementHandle.evalOnSelectorAll", { title: "Evaluate", snapshot: true, pause: true }], + ["ElementHandle.boundingBox", { title: "Get bounding box", snapshot: true, pause: true }], + ["ElementHandle.check", { title: "Check", slowMo: true, snapshot: true, pause: true, input: true, isAutoWaiting: true }], + ["ElementHandle.click", { title: "Click", slowMo: true, snapshot: true, pause: true, input: true, isAutoWaiting: true }], + ["ElementHandle.contentFrame", { title: "Get content frame", group: "getter" }], + ["ElementHandle.dblclick", { title: "Double click", slowMo: true, snapshot: true, pause: true, input: true, isAutoWaiting: true }], + ["ElementHandle.dispatchEvent", { title: "Dispatch event", slowMo: true, snapshot: true, pause: true }], + ["ElementHandle.fill", { title: 'Fill "{value}"', slowMo: true, snapshot: true, pause: true, input: true, isAutoWaiting: true }], + ["ElementHandle.focus", { title: "Focus", slowMo: true, snapshot: true, pause: true }], + ["ElementHandle.getAttribute", { title: "Get attribute", snapshot: true, pause: true, group: "getter" }], + ["ElementHandle.hover", { title: "Hover", slowMo: true, snapshot: true, pause: true, input: true, isAutoWaiting: true }], + ["ElementHandle.innerHTML", { title: "Get HTML", snapshot: true, pause: true, group: "getter" }], + ["ElementHandle.innerText", { title: "Get inner text", snapshot: true, pause: true, group: "getter" }], + ["ElementHandle.inputValue", { title: "Get input value", snapshot: true, pause: true, group: "getter" }], + ["ElementHandle.isChecked", { title: "Is checked", snapshot: true, pause: true, group: "getter" }], + ["ElementHandle.isDisabled", { title: "Is disabled", snapshot: true, pause: true, group: "getter" }], + ["ElementHandle.isEditable", { title: "Is editable", snapshot: true, pause: true, group: "getter" }], + ["ElementHandle.isEnabled", { title: "Is enabled", snapshot: true, pause: true, group: "getter" }], + ["ElementHandle.isHidden", { title: "Is hidden", snapshot: true, pause: true, group: "getter" }], + ["ElementHandle.isVisible", { title: "Is visible", snapshot: true, pause: true, group: "getter" }], + ["ElementHandle.ownerFrame", { title: "Get owner frame", group: "getter" }], + ["ElementHandle.press", { title: 'Press "{key}"', slowMo: true, snapshot: true, pause: true, input: true, isAutoWaiting: true }], + ["ElementHandle.querySelector", { title: "Query selector", snapshot: true }], + ["ElementHandle.querySelectorAll", { title: "Query selector all", snapshot: true }], + ["ElementHandle.screenshot", { title: "Screenshot", snapshot: true, pause: true }], + ["ElementHandle.scrollIntoViewIfNeeded", { title: "Scroll into view", slowMo: true, snapshot: true, pause: true }], + ["ElementHandle.selectOption", { title: "Select option", slowMo: true, snapshot: true, pause: true, input: true, isAutoWaiting: true }], + ["ElementHandle.selectText", { title: "Select text", slowMo: true, snapshot: true, pause: true }], + ["ElementHandle.setInputFiles", { title: "Set input files", slowMo: true, snapshot: true, pause: true, input: true, isAutoWaiting: true }], + ["ElementHandle.tap", { title: "Tap", slowMo: true, snapshot: true, pause: true, input: true, isAutoWaiting: true }], + ["ElementHandle.textContent", { title: "Get text content", snapshot: true, pause: true, group: "getter" }], + ["ElementHandle.type", { title: "Type", slowMo: true, snapshot: true, pause: true, input: true, isAutoWaiting: true }], + ["ElementHandle.uncheck", { title: "Uncheck", slowMo: true, snapshot: true, pause: true, input: true, isAutoWaiting: true }], + ["ElementHandle.waitForElementState", { title: "Wait for state", snapshot: true, pause: true }], + ["ElementHandle.waitForSelector", { title: "Wait for selector", snapshot: true }], + ["LocalUtils.zip", { internal: true }], + ["LocalUtils.harOpen", { internal: true }], + ["LocalUtils.harLookup", { internal: true }], + ["LocalUtils.harClose", { internal: true }], + ["LocalUtils.harUnzip", { internal: true }], + ["LocalUtils.connect", { internal: true }], + ["LocalUtils.tracingStarted", { internal: true }], + ["LocalUtils.addStackToTracingNoReply", { internal: true }], + ["LocalUtils.traceDiscarded", { internal: true }], + ["LocalUtils.globToRegex", { internal: true }], + ["Request.response", { internal: true }], + ["Request.rawRequestHeaders", { internal: true }], + ["Route.redirectNavigationRequest", { internal: true }], + ["Route.abort", { title: "Abort request", group: "route" }], + ["Route.continue", { title: "Continue request", group: "route" }], + ["Route.fulfill", { title: "Fulfill request", group: "route" }], + ["WebSocketRoute.connect", { title: "Connect WebSocket to server", group: "route" }], + ["WebSocketRoute.ensureOpened", { internal: true }], + ["WebSocketRoute.sendToPage", { title: "Send WebSocket message", group: "route" }], + ["WebSocketRoute.sendToServer", { title: "Send WebSocket message", group: "route" }], + ["WebSocketRoute.closePage", { internal: true }], + ["WebSocketRoute.closeServer", { internal: true }], + ["Response.body", { title: "Get response body", group: "getter" }], + ["Response.securityDetails", { internal: true }], + ["Response.serverAddr", { internal: true }], + ["Response.rawResponseHeaders", { internal: true }], + ["Response.httpVersion", { internal: true }], + ["Response.sizes", { internal: true }], + ["Page.addInitScript", { title: "Add init script", group: "configuration" }], + ["Page.close", { title: "Close page", pause: true, potentiallyClosesScope: true }], + ["Page.runBeforeUnload", { title: "Run beforeunload", pause: true }], + ["Page.clearConsoleMessages", { title: "Clear console messages" }], + ["Page.consoleMessages", { title: "Get console messages", group: "getter" }], + ["Page.emulateMedia", { title: "Emulate media", snapshot: true, pause: true }], + ["Page.exposeBinding", { title: "Expose binding", group: "configuration" }], + ["Page.goBack", { title: "Go back", slowMo: true, snapshot: true, pause: true }], + ["Page.goForward", { title: "Go forward", slowMo: true, snapshot: true, pause: true }], + ["Page.requestGC", { title: "Request garbage collection", group: "configuration" }], + ["Page.registerLocatorHandler", { title: "Register locator handler" }], + ["Page.resolveLocatorHandlerNoReply", { internal: true }], + ["Page.unregisterLocatorHandler", { title: "Unregister locator handler" }], + ["Page.reload", { title: "Reload", slowMo: true, snapshot: true, pause: true }], + ["Page.expectScreenshot", { title: "Expect screenshot", snapshot: true, pause: true }], + ["Page.screenshot", { title: "Screenshot", snapshot: true, pause: true }], + ["Page.setExtraHTTPHeaders", { title: "Set extra HTTP headers", group: "configuration" }], + ["Page.setNetworkInterceptionPatterns", { title: "Route requests", group: "route" }], + ["Page.setWebSocketInterceptionPatterns", { title: "Route WebSockets", group: "route" }], + ["Page.setViewportSize", { title: "Set viewport size", snapshot: true, pause: true }], + ["Page.keyboardDown", { title: 'Key down "{key}"', slowMo: true, snapshot: true, pause: true, input: true }], + ["Page.keyboardUp", { title: 'Key up "{key}"', slowMo: true, snapshot: true, pause: true, input: true }], + ["Page.keyboardInsertText", { title: 'Insert "{text}"', slowMo: true, snapshot: true, pause: true, input: true }], + ["Page.keyboardType", { title: 'Type "{text}"', slowMo: true, snapshot: true, pause: true, input: true }], + ["Page.keyboardPress", { title: 'Press "{key}"', slowMo: true, snapshot: true, pause: true, input: true }], + ["Page.mouseMove", { title: "Mouse move", slowMo: true, snapshot: true, pause: true, input: true }], + ["Page.mouseDown", { title: "Mouse down", slowMo: true, snapshot: true, pause: true, input: true }], + ["Page.mouseUp", { title: "Mouse up", slowMo: true, snapshot: true, pause: true, input: true }], + ["Page.mouseClick", { title: "Click", slowMo: true, snapshot: true, pause: true, input: true }], + ["Page.mouseWheel", { title: "Mouse wheel", slowMo: true, snapshot: true, pause: true, input: true }], + ["Page.touchscreenTap", { title: "Tap", slowMo: true, snapshot: true, pause: true, input: true }], + ["Page.clearPageErrors", { title: "Clear page errors" }], + ["Page.pageErrors", { title: "Get page errors", group: "getter" }], + ["Page.pdf", { title: "PDF" }], + ["Page.requests", { title: "Get network requests", group: "getter" }], + ["Page.startJSCoverage", { title: "Start JS coverage", group: "configuration" }], + ["Page.stopJSCoverage", { title: "Stop JS coverage", group: "configuration" }], + ["Page.startCSSCoverage", { title: "Start CSS coverage", group: "configuration" }], + ["Page.stopCSSCoverage", { title: "Stop CSS coverage", group: "configuration" }], + ["Page.bringToFront", { title: "Bring to front" }], + ["Page.pickLocator", { title: "Pick locator", group: "configuration" }], + ["Page.cancelPickLocator", { title: "Cancel pick locator", group: "configuration" }], + ["Page.hideHighlight", { title: "Hide all element highlights", group: "configuration" }], + ["Page.screencastShowOverlay", { title: "Show overlay", group: "configuration" }], + ["Page.screencastRemoveOverlay", { title: "Remove overlay", group: "configuration" }], + ["Page.screencastChapter", { title: "Show chapter overlay", group: "configuration" }], + ["Page.screencastSetOverlayVisible", { title: "Set overlay visibility", group: "configuration" }], + ["Page.screencastShowActions", { title: "Show actions", group: "configuration" }], + ["Page.screencastHideActions", { title: "Remove actions", group: "configuration" }], + ["Page.screencastStart", { title: "Start screencast", group: "configuration" }], + ["Page.screencastStop", { title: "Stop screencast", group: "configuration" }], + ["Page.updateSubscription", { internal: true }], + ["Page.setDockTile", { internal: true }], + ["Page.webStorageItems", { title: "Get WebStorage items", group: "getter" }], + ["Page.webStorageGetItem", { title: "Get WebStorage item", group: "getter" }], + ["Page.webStorageSetItem", { title: "Set WebStorage item", group: "configuration" }], + ["Page.webStorageRemoveItem", { title: "Remove WebStorage item", group: "configuration" }], + ["Page.webStorageClear", { title: "Clear WebStorage", group: "configuration" }], + ["Root.initialize", { internal: true }], + ["Playwright.newRequest", { title: "Create request context" }], + ["DebugController.initialize", { internal: true }], + ["DebugController.setReportStateChanged", { internal: true }], + ["DebugController.setRecorderMode", { internal: true }], + ["DebugController.highlight", { internal: true }], + ["DebugController.hideHighlight", { internal: true }], + ["DebugController.resume", { internal: true }], + ["DebugController.kill", { internal: true }], + ["SocksSupport.socksConnected", { internal: true }], + ["SocksSupport.socksFailed", { internal: true }], + ["SocksSupport.socksData", { internal: true }], + ["SocksSupport.socksError", { internal: true }], + ["SocksSupport.socksEnd", { internal: true }], + ["JsonPipe.send", { internal: true }], + ["JsonPipe.close", { internal: true }], + ["CDPSession.send", { title: "Send CDP command", group: "configuration" }], + ["CDPSession.detach", { title: "Detach CDP session", potentiallyClosesScope: true, group: "configuration" }], + ["BindingCall.reject", { internal: true }], + ["BindingCall.resolve", { internal: true }], + ["Debugger.requestPause", { title: "Pause on next call", group: "configuration" }], + ["Debugger.resume", { title: "Resume", group: "configuration" }], + ["Debugger.next", { title: "Step to next call", group: "configuration" }], + ["Debugger.runTo", { title: "Run to location", group: "configuration" }], + ["Dialog.accept", { title: "Accept dialog" }], + ["Dialog.dismiss", { title: "Dismiss dialog" }], + ["Tracing.tracingStart", { title: "Start tracing", group: "configuration" }], + ["Tracing.tracingStartChunk", { title: "Start tracing", group: "configuration" }], + ["Tracing.tracingGroup", { title: 'Trace "{name}"' }], + ["Tracing.tracingGroupEnd", { title: "Group end" }], + ["Tracing.tracingStopChunk", { title: "Stop tracing", group: "configuration" }], + ["Tracing.tracingStop", { title: "Stop tracing", group: "configuration" }], + ["Tracing.harStart", { internal: true }], + ["Tracing.harExport", { internal: true }], + ["Worker.disconnect", { title: "Disconnect from worker", potentiallyClosesScope: true }], + ["Worker.evaluateExpression", { title: "Evaluate" }], + ["Worker.evaluateExpressionHandle", { title: "Evaluate" }], + ["Worker.updateSubscription", { internal: true }] + ]); + } +}); + +// packages/isomorphic/protocolFormatter.ts +function formatProtocolParam(params2, alternatives) { + return _formatProtocolParam(params2, alternatives)?.replaceAll("\n", "\\n"); +} +function _formatProtocolParam(params2, alternatives) { + if (!params2) + return void 0; + for (const name of alternatives.split("|")) { + if (name === "url") { + try { + const urlObject = new URL(params2[name]); + if (urlObject.protocol === "data:") + return urlObject.protocol; + if (["about:", "chrome:", "edge:"].includes(urlObject.protocol)) + return params2[name]; + return urlObject.pathname + urlObject.search; + } catch (error) { + if (params2[name] !== void 0) + return params2[name]; + } + } + if (name === "timeNumber" && params2[name] !== void 0) { + return new Date(params2[name]).toString(); + } + const value2 = deepParam(params2, name); + if (value2 !== void 0) + return value2; + } +} +function deepParam(params2, name) { + const tokens = name.split("."); + let current = params2; + for (const token of tokens) { + if (typeof current !== "object" || current === null) + return void 0; + current = current[token]; + } + if (current === void 0) + return void 0; + return String(current); +} +function renderTitleForCall(metadata) { + const titleFormat = metadata.title ?? getMetainfo(metadata)?.title ?? metadata.method; + return titleFormat.replace(/\{([^}]+)\}/g, (fullMatch, p1) => { + return formatProtocolParam(metadata.params, p1) ?? fullMatch; + }); +} +function getActionGroup(metadata) { + return getMetainfo(metadata)?.group; +} +var init_protocolFormatter = __esm({ + "packages/isomorphic/protocolFormatter.ts"() { + "use strict"; + init_protocolMetainfo(); + } +}); + +// packages/isomorphic/semaphore.ts +var Semaphore; +var init_semaphore = __esm({ + "packages/isomorphic/semaphore.ts"() { + "use strict"; + init_manualPromise(); + Semaphore = class { + constructor(max) { + this._acquired = 0; + this._queue = []; + this._max = max; + } + setMax(max) { + this._max = max; + } + acquire() { + const lock2 = new ManualPromise(); + this._queue.push(lock2); + this._flush(); + return lock2; + } + release() { + --this._acquired; + this._flush(); + } + _flush() { + while (this._acquired < this._max && this._queue.length) { + ++this._acquired; + this._queue.shift().resolve(); + } + } + }; + } +}); + +// packages/isomorphic/formatUtils.ts +function msToString(ms) { + if (ms < 0 || !isFinite(ms)) + return "-"; + if (ms === 0) + return "0ms"; + if (ms < 1e3) + return ms.toFixed(0) + "ms"; + const seconds = ms / 1e3; + if (seconds < 60) + return seconds.toFixed(1) + "s"; + const minutes = seconds / 60; + if (minutes < 60) + return minutes.toFixed(1) + "m"; + const hours = minutes / 60; + if (hours < 24) + return hours.toFixed(1) + "h"; + const days = hours / 24; + return days.toFixed(1) + "d"; +} +function bytesToString(bytes) { + if (bytes < 0 || !isFinite(bytes)) + return "-"; + if (bytes === 0) + return "0"; + if (bytes < 1e3) + return bytes.toFixed(0); + const kb = bytes / 1024; + if (kb < 1e3) + return kb.toFixed(1) + "K"; + const mb = kb / 1024; + if (mb < 1e3) + return mb.toFixed(1) + "M"; + const gb = mb / 1024; + return gb.toFixed(1) + "G"; +} +var init_formatUtils = __esm({ + "packages/isomorphic/formatUtils.ts"() { + "use strict"; + } +}); + +// packages/isomorphic/time.ts +function setTimeOrigin(origin) { + _timeOrigin = origin; + _timeShift = performance.timeOrigin - origin; +} +function timeOrigin() { + return _timeOrigin; +} +function monotonicTime() { + return Math.floor((performance.now() + _timeShift) * 1e3) / 1e3; +} +var _timeOrigin, _timeShift, DEFAULT_PLAYWRIGHT_TIMEOUT, DEFAULT_PLAYWRIGHT_LAUNCH_TIMEOUT; +var init_time = __esm({ + "packages/isomorphic/time.ts"() { + "use strict"; + _timeOrigin = performance.timeOrigin; + _timeShift = 0; + DEFAULT_PLAYWRIGHT_TIMEOUT = 3e4; + DEFAULT_PLAYWRIGHT_LAUNCH_TIMEOUT = 3 * 60 * 1e3; + } +}); + +// packages/isomorphic/timeoutRunner.ts +async function raceAgainstDeadline(cb, deadline) { + let timer; + return await Promise.race([ + cb().then((result2) => { + return { result: result2, timedOut: false }; + }), + new Promise((resolve) => { + if (!deadline) + return; + timer = setTimeout(() => resolve({ timedOut: true }), deadline - monotonicTime()); + }) + ]).finally(() => { + clearTimeout(timer); + }); +} +async function pollAgainstDeadline(callback, deadline, pollIntervals = [100, 250, 500, 1e3]) { + const lastPollInterval = pollIntervals.pop() ?? 1e3; + let lastResult; + const wrappedCallback = () => Promise.resolve().then(callback); + while (true) { + const time = monotonicTime(); + if (deadline && time >= deadline) + break; + const received = await raceAgainstDeadline(wrappedCallback, deadline); + if (received.timedOut) + break; + lastResult = received.result.result; + if (!received.result.continuePolling) + return { result: lastResult, timedOut: false }; + const interval = pollIntervals.shift() ?? lastPollInterval; + if (deadline && deadline <= monotonicTime() + interval) + break; + await new Promise((x) => setTimeout(x, interval)); + } + return { timedOut: true, result: lastResult }; +} +var init_timeoutRunner = __esm({ + "packages/isomorphic/timeoutRunner.ts"() { + "use strict"; + init_time(); + } +}); + +// packages/isomorphic/trace/snapshotServer.ts +function removeHash(url2) { + try { + const u = new URL(url2); + u.hash = ""; + return u.toString(); + } catch (e) { + return url2; + } +} +var SnapshotServer; +var init_snapshotServer = __esm({ + "packages/isomorphic/trace/snapshotServer.ts"() { + "use strict"; + SnapshotServer = class { + constructor(snapshotStorage, resourceLoader) { + this._snapshotIds = /* @__PURE__ */ new Map(); + this._snapshotStorage = snapshotStorage; + this._resourceLoader = resourceLoader; + } + serveSnapshot(pageOrFrameId, searchParams, snapshotUrl) { + const snapshot3 = this._snapshot(pageOrFrameId, searchParams); + if (!snapshot3) + return new Response(null, { status: 404 }); + const renderedSnapshot = snapshot3.render(); + this._snapshotIds.set(snapshotUrl, snapshot3); + return new Response(renderedSnapshot.html, { status: 200, headers: { "Content-Type": "text/html; charset=utf-8" } }); + } + async serveClosestScreenshot(pageOrFrameId, searchParams) { + const snapshot3 = this._snapshot(pageOrFrameId, searchParams); + const sha1 = snapshot3?.closestScreenshot(); + if (!sha1) + return new Response(null, { status: 404 }); + return new Response(await this._resourceLoader(sha1)); + } + serveSnapshotInfo(pageOrFrameId, searchParams) { + const snapshot3 = this._snapshot(pageOrFrameId, searchParams); + return this._respondWithJson(snapshot3 ? { + viewport: snapshot3.viewport(), + url: snapshot3.snapshot().frameUrl, + timestamp: snapshot3.snapshot().timestamp, + wallTime: snapshot3.snapshot().wallTime + } : { + error: "No snapshot found" + }); + } + _snapshot(pageOrFrameId, params2) { + const name = params2.get("name"); + return this._snapshotStorage.snapshotByName(pageOrFrameId, name); + } + _respondWithJson(object) { + return new Response(JSON.stringify(object), { + status: 200, + headers: { + "Cache-Control": "public, max-age=31536000", + "Content-Type": "application/json" + } + }); + } + async serveResource(requestUrlAlternatives, method, snapshotUrl) { + let resource; + const snapshot3 = this._snapshotIds.get(snapshotUrl); + for (const requestUrl of requestUrlAlternatives) { + resource = snapshot3?.resourceByUrl(removeHash(requestUrl), method); + if (resource) + break; + } + if (!resource) + return new Response(null, { status: 404 }); + const sha1 = resource.response.content._sha1; + const content = sha1 ? await this._resourceLoader(sha1) || new Blob([]) : new Blob([]); + let contentType = resource.response.content.mimeType; + const isTextEncoding = /^text\/|^application\/(javascript|json)/.test(contentType); + if (isTextEncoding && !contentType.includes("charset")) + contentType = `${contentType}; charset=utf-8`; + const headers = new Headers(); + if (contentType !== "x-unknown") + headers.set("Content-Type", contentType); + for (const { name, value: value2 } of resource.response.headers) + headers.set(name, value2); + headers.delete("Content-Encoding"); + headers.delete("Access-Control-Allow-Origin"); + headers.set("Access-Control-Allow-Origin", "*"); + headers.delete("Content-Length"); + headers.set("Content-Length", String(content.size)); + if (this._snapshotStorage.hasResourceOverride(resource.request.url)) + headers.set("Cache-Control", "no-store, no-cache, max-age=0"); + else + headers.set("Cache-Control", "public, max-age=31536000"); + const { status } = resource.response; + const isNullBodyStatus = status === 101 || status === 204 || status === 205 || status === 304; + return new Response(isNullBodyStatus ? null : content, { + headers, + status: resource.response.status, + statusText: resource.response.statusText + }); + } + }; + } +}); + +// packages/isomorphic/urlMatch.ts +function isHttpUrl(url2, base) { + try { + return ["http:", "https:"].includes(new URL(url2, base).protocol); + } catch { + return false; + } +} +function globToRegexPattern(glob) { + const tokens = ["^"]; + let inGroup = false; + for (let i = 0; i < glob.length; ++i) { + const c = glob[i]; + if (c === "\\" && i + 1 < glob.length) { + const char = glob[++i]; + tokens.push(escapedChars.has(char) ? "\\" + char : char); + continue; + } + if (c === "*") { + const charBefore = glob[i - 1]; + let starCount = 1; + while (glob[i + 1] === "*") { + starCount++; + i++; + } + if (starCount > 1) { + const charAfter = glob[i + 1]; + if (charAfter === "/") { + if (charBefore === "/") + tokens.push("((.+/)|)"); + else + tokens.push("(.*/)"); + ++i; + } else { + tokens.push("(.*)"); + } + } else { + tokens.push("([^/]*)"); + } + continue; + } + switch (c) { + case "{": + if (inGroup) + throw new Error(`Invalid glob pattern ${JSON.stringify(glob)}: nested '{' is not supported`); + inGroup = true; + tokens.push("("); + break; + case "}": + if (!inGroup) + throw new Error(`Invalid glob pattern ${JSON.stringify(glob)}: unmatched '}'`); + inGroup = false; + tokens.push(")"); + break; + case ",": + if (inGroup) { + tokens.push("|"); + break; + } + tokens.push("\\" + c); + break; + default: + tokens.push(escapedChars.has(c) ? "\\" + c : c); + } + } + if (inGroup) + throw new Error(`Invalid glob pattern ${JSON.stringify(glob)}: unmatched '{'`); + tokens.push("$"); + return tokens.join(""); +} +function isRegExp3(obj) { + return obj instanceof RegExp || Object.prototype.toString.call(obj) === "[object RegExp]"; +} +function serializeURLPattern(v) { + return { + hash: v.hash, + hostname: v.hostname, + password: v.password, + pathname: v.pathname, + port: v.port, + protocol: v.protocol, + search: v.search, + username: v.username + }; +} +function serializeURLMatch(match) { + if (isString(match)) + return { glob: match }; + if (isRegExp3(match)) + return { regexSource: match.source, regexFlags: match.flags }; + if (isURLPattern(match)) + return { urlPattern: serializeURLPattern(match) }; + return void 0; +} +function deserializeURLPattern(v) { + if (typeof globalThis.URLPattern !== "function") + return () => true; + return new globalThis.URLPattern({ + hash: v.hash, + hostname: v.hostname, + password: v.password, + pathname: v.pathname, + port: v.port, + protocol: v.protocol, + search: v.search, + username: v.username + }); +} +function deserializeURLMatch(match) { + if (match.regexSource) + return new RegExp(match.regexSource, match.regexFlags); + if (match.urlPattern) + return deserializeURLPattern(match.urlPattern); + return match.glob; +} +function urlMatchesEqual(match1, match2) { + if (isRegExp3(match1) && isRegExp3(match2)) + return match1.source === match2.source && match1.flags === match2.flags; + return match1 === match2; +} +function urlMatches(baseURL, urlString, match, webSocketUrl) { + if (match === void 0 || match === "") + return true; + if (isString(match)) + match = new RegExp(resolveGlobToRegexPattern(baseURL, match, webSocketUrl)); + if (isRegExp3(match)) { + const r = match.test(urlString); + return r; + } + const url2 = parseURL(urlString); + if (!url2) + return false; + if (isURLPattern(match)) + return match.test(url2.href); + if (typeof match !== "function") + throw new Error("url parameter should be string, RegExp, URLPattern or function"); + return match(url2); +} +function resolveGlobToRegexPattern(baseURL, glob, webSocketUrl) { + if (webSocketUrl) + baseURL = toWebSocketBaseUrl(baseURL); + glob = resolveGlobBase(baseURL, glob); + return globToRegexPattern(glob); +} +function toWebSocketBaseUrl(baseURL) { + if (baseURL && /^https?:\/\//.test(baseURL)) + baseURL = baseURL.replace(/^http/, "ws"); + return baseURL; +} +function resolveGlobBase(baseURL, match) { + if (!match.startsWith("*")) { + let mapToken2 = function(original, replacement) { + if (original.length === 0) + return ""; + tokenMap.set(replacement, original); + return replacement; + }; + var mapToken = mapToken2; + const tokenMap = /* @__PURE__ */ new Map(); + match = match.replaceAll(/\\\\\?/g, "?"); + if (match.startsWith("about:") || match.startsWith("data:") || match.startsWith("chrome:") || match.startsWith("edge:") || match.startsWith("file:")) + return match; + const relativePath = match.split("/").map((token, index) => { + if (token === "." || token === ".." || token === "") + return token; + if (index === 0 && token.endsWith(":")) { + if (token.indexOf("*") !== -1 || token.indexOf("{") !== -1) + return mapToken2(token, "http:"); + return token; + } + const questionIndex = token.indexOf("?"); + if (questionIndex === -1) + return mapToken2(token, `$_${index}_$`); + const newPrefix = mapToken2(token.substring(0, questionIndex), `$_${index}_$`); + const newSuffix = mapToken2(token.substring(questionIndex), `?$_${index}_$`); + return newPrefix + newSuffix; + }).join("/"); + const result2 = resolveBaseURL(baseURL, relativePath); + let resolved = result2.resolved; + for (const [token, original] of tokenMap) { + const normalize = result2.caseInsensitivePart?.includes(token); + resolved = resolved.replace(token, normalize ? original.toLowerCase() : original); + } + match = resolved; + } + return match; +} +function parseURL(url2) { + try { + return new URL(url2); + } catch (e) { + return null; + } +} +function constructURLBasedOnBaseURL(baseURL, givenURL) { + try { + return resolveBaseURL(baseURL, givenURL).resolved; + } catch (e) { + return givenURL; + } +} +function resolveBaseURL(baseURL, givenURL) { + try { + const url2 = new URL(givenURL, baseURL); + const resolved = url2.toString(); + const caseInsensitivePrefix = url2.origin; + return { resolved, caseInsensitivePart: caseInsensitivePrefix }; + } catch (e) { + return { resolved: givenURL }; + } +} +var escapedChars, isURLPattern; +var init_urlMatch = __esm({ + "packages/isomorphic/urlMatch.ts"() { + "use strict"; + init_stringUtils(); + escapedChars = /* @__PURE__ */ new Set(["$", "^", "+", ".", "*", "(", ")", "|", "\\", "?", "{", "}", "[", "]"]); + isURLPattern = (v) => typeof globalThis.URLPattern === "function" && v instanceof globalThis.URLPattern; + } +}); + +// packages/isomorphic/locatorUtils.ts +function getByAttributeTextSelector(attrName, text2, options) { + return `internal:attr=[${attrName}=${escapeForAttributeSelector(text2, options?.exact || false)}]`; +} +function encodeTestIdAttributeName(testIdAttributeName2) { + return testIdAttributeName2.includes(",") ? JSON.stringify(testIdAttributeName2) : testIdAttributeName2; +} +function getByTestIdSelector(testIdAttributeName2, testId) { + return `internal:testid=[${encodeTestIdAttributeName(testIdAttributeName2)}=${escapeForAttributeSelector(testId, true)}]`; +} +function getByLabelSelector(text2, options) { + return "internal:label=" + escapeForTextSelector(text2, !!options?.exact); +} +function getByAltTextSelector(text2, options) { + return getByAttributeTextSelector("alt", text2, options); +} +function getByTitleSelector(text2, options) { + return getByAttributeTextSelector("title", text2, options); +} +function getByPlaceholderSelector(text2, options) { + return getByAttributeTextSelector("placeholder", text2, options); +} +function getByTextSelector(text2, options) { + return "internal:text=" + escapeForTextSelector(text2, !!options?.exact); +} +function getByRoleSelector(role, options = {}) { + const props = []; + if (options.checked !== void 0) + props.push(["checked", String(options.checked)]); + if (options.disabled !== void 0) + props.push(["disabled", String(options.disabled)]); + if (options.selected !== void 0) + props.push(["selected", String(options.selected)]); + if (options.expanded !== void 0) + props.push(["expanded", String(options.expanded)]); + if (options.includeHidden !== void 0) + props.push(["include-hidden", String(options.includeHidden)]); + if (options.level !== void 0) + props.push(["level", String(options.level)]); + if (options.name !== void 0) + props.push(["name", escapeForAttributeSelector(options.name, !!options.exact)]); + if (options.description !== void 0) + props.push(["description", escapeForAttributeSelector(options.description, !!options.exact)]); + if (options.pressed !== void 0) + props.push(["pressed", String(options.pressed)]); + return `internal:role=${role}${props.map(([n, v]) => `[${n}=${v}]`).join("")}`; +} +var init_locatorUtils = __esm({ + "packages/isomorphic/locatorUtils.ts"() { + "use strict"; + init_stringUtils(); + } +}); + +// packages/isomorphic/locatorParser.ts +function parseLocator(locator2, testIdAttributeName2) { + locator2 = locator2.replace(/AriaRole\s*\.\s*([\w]+)/g, (_, group) => group.toLowerCase()).replace(/(get_by_role|getByRole)\s*\(\s*(?:["'`])([^'"`]+)['"`]/g, (_, group1, group2) => `${group1}(${group2.toLowerCase()}`); + const params2 = []; + let template = ""; + for (let i = 0; i < locator2.length; ++i) { + const quote5 = locator2[i]; + if (quote5 !== '"' && quote5 !== "'" && quote5 !== "`" && quote5 !== "/") { + template += quote5; + continue; + } + const isRegexEscaping = locator2[i - 1] === "r" || locator2[i] === "/"; + ++i; + let text2 = ""; + while (i < locator2.length) { + if (locator2[i] === "\\") { + if (isRegexEscaping) { + if (locator2[i + 1] !== quote5) + text2 += locator2[i]; + ++i; + text2 += locator2[i]; + } else { + ++i; + if (locator2[i] === "n") + text2 += "\n"; + else if (locator2[i] === "r") + text2 += "\r"; + else if (locator2[i] === "t") + text2 += " "; + else + text2 += locator2[i]; + } + ++i; + continue; + } + if (locator2[i] !== quote5) { + text2 += locator2[i++]; + continue; + } + break; + } + params2.push({ quote: quote5, text: text2 }); + template += (quote5 === "/" ? "r" : "") + "$" + params2.length; + } + template = template.toLowerCase().replace(/get_by_alt_text/g, "getbyalttext").replace(/get_by_test_id/g, "getbytestid").replace(/get_by_([\w]+)/g, "getby$1").replace(/has_not_text/g, "hasnottext").replace(/has_text/g, "hastext").replace(/has_not/g, "hasnot").replace(/frame_locator/g, "framelocator").replace(/content_frame/g, "contentframe").replace(/[{}\s]/g, "").replace(/new\(\)/g, "").replace(/new[\w]+\.[\w]+options\(\)/g, "").replace(/\.set/g, ",set").replace(/\.or_\(/g, "or(").replace(/\.and_\(/g, "and(").replace(/:/g, "=").replace(/,re\.ignorecase/g, "i").replace(/,pattern.case_insensitive/g, "i").replace(/,regexoptions.ignorecase/g, "i").replace(/re.compile\(([^)]+)\)/g, "$1").replace(/pattern.compile\(([^)]+)\)/g, "r$1").replace(/newregex\(([^)]+)\)/g, "r$1").replace(/string=/g, "=").replace(/regex=/g, "=").replace(/,,/g, ",").replace(/,\)/g, ")"); + const preferredQuote = params2.map((p) => p.quote).filter((quote5) => "'\"`".includes(quote5))[0]; + return { selector: transform(template, params2, testIdAttributeName2), preferredQuote }; +} +function countParams(template) { + return [...template.matchAll(/\$\d+/g)].length; +} +function shiftParams(template, sub) { + return template.replace(/\$(\d+)/g, (_, ordinal) => `$${ordinal - sub}`); +} +function transform(template, params2, testIdAttributeName2) { + while (true) { + const hasMatch = template.match(/filter\(,?(has=|hasnot=|sethas\(|sethasnot\()/); + if (!hasMatch) + break; + const start3 = hasMatch.index + hasMatch[0].length; + let balance = 0; + let end = start3; + for (; end < template.length; end++) { + if (template[end] === "(") + balance++; + else if (template[end] === ")") + balance--; + if (balance < 0) + break; + } + let prefix = template.substring(0, start3); + let extraSymbol = 0; + if (["sethas(", "sethasnot("].includes(hasMatch[1])) { + extraSymbol = 1; + prefix = prefix.replace(/sethas\($/, "has=").replace(/sethasnot\($/, "hasnot="); + } + const paramsCountBeforeHas = countParams(template.substring(0, start3)); + const hasTemplate = shiftParams(template.substring(start3, end), paramsCountBeforeHas); + const paramsCountInHas = countParams(hasTemplate); + const hasParams = params2.slice(paramsCountBeforeHas, paramsCountBeforeHas + paramsCountInHas); + const hasSelector = JSON.stringify(transform(hasTemplate, hasParams, testIdAttributeName2)); + template = prefix.replace(/=$/, "2=") + `$${paramsCountBeforeHas + 1}` + shiftParams(template.substring(end + extraSymbol), paramsCountInHas - 1); + const paramsBeforeHas = params2.slice(0, paramsCountBeforeHas); + const paramsAfterHas = params2.slice(paramsCountBeforeHas + paramsCountInHas); + params2 = paramsBeforeHas.concat([{ quote: '"', text: hasSelector }]).concat(paramsAfterHas); + } + template = template.replace(/\,set([\w]+)\(([^)]+)\)/g, (_, group1, group2) => "," + group1.toLowerCase() + "=" + group2.toLowerCase()).replace(/framelocator\(([^)]+)\)/g, "$1.internal:control=enter-frame").replace(/contentframe(\(\))?/g, "internal:control=enter-frame").replace(/locator\(([^)]+),hastext=([^),]+)\)/g, "locator($1).internal:has-text=$2").replace(/locator\(([^)]+),hasnottext=([^),]+)\)/g, "locator($1).internal:has-not-text=$2").replace(/locator\(([^)]+),hastext=([^),]+)\)/g, "locator($1).internal:has-text=$2").replace(/locator\(([^)]+)\)/g, "$1").replace(/getbyrole\(([^)]+)\)/g, "internal:role=$1").replace(/getbytext\(([^)]+)\)/g, "internal:text=$1").replace(/getbylabel\(([^)]+)\)/g, "internal:label=$1").replace(/getbytestid\(([^)]+)\)/g, `internal:testid=[${encodeTestIdAttributeName(testIdAttributeName2)}=$1]`).replace(/getby(placeholder|alt|title)(?:text)?\(([^)]+)\)/g, "internal:attr=[$1=$2]").replace(/first(\(\))?/g, "nth=0").replace(/last(\(\))?/g, "nth=-1").replace(/nth\(([^)]+)\)/g, "nth=$1").replace(/filter\(,?visible=true\)/g, "visible=true").replace(/filter\(,?visible=false\)/g, "visible=false").replace(/filter\(,?hastext=([^)]+)\)/g, "internal:has-text=$1").replace(/filter\(,?hasnottext=([^)]+)\)/g, "internal:has-not-text=$1").replace(/filter\(,?has2=([^)]+)\)/g, "internal:has=$1").replace(/filter\(,?hasnot2=([^)]+)\)/g, "internal:has-not=$1").replace(/,exact=false/g, "").replace(/(,name=\$\d+)(,description=\$\d+),exact=true/g, "$1s$2s").replace(/,exact=true/g, "s").replace(/,includehidden=/g, ",include-hidden=").replace(/\,/g, "]["); + const parts = template.split("."); + for (let index = 0; index < parts.length - 1; index++) { + if (parts[index] === "internal:control=enter-frame" && parts[index + 1].startsWith("nth=")) { + const [nth] = parts.splice(index, 1); + parts.splice(index + 1, 0, nth); + } + } + return parts.map((t) => { + if (!t.startsWith("internal:") || t === "internal:control") + return t.replace(/\$(\d+)/g, (_, ordinal) => { + const param = params2[+ordinal - 1]; + return param.text; + }); + t = t.includes("[") ? t.replace(/\]/, "") + "]" : t; + t = t.replace(/(?:r)\$(\d+)(i)?/g, (_, ordinal, suffix) => { + const param = params2[+ordinal - 1]; + if (t.startsWith("internal:attr") || t.startsWith("internal:testid") || t.startsWith("internal:role")) + return escapeForAttributeSelector(new RegExp(param.text), false) + (suffix || ""); + return escapeForTextSelector(new RegExp(param.text, suffix), false); + }).replace(/\$(\d+)(i|s)?/g, (_, ordinal, suffix) => { + const param = params2[+ordinal - 1]; + if (t.startsWith("internal:has=") || t.startsWith("internal:has-not=")) + return param.text; + if (t.startsWith("internal:testid")) + return escapeForAttributeSelector(param.text, true); + if (t.startsWith("internal:attr") || t.startsWith("internal:role")) + return escapeForAttributeSelector(param.text, suffix === "s"); + return escapeForTextSelector(param.text, suffix === "s"); + }); + return t; + }).join(" >> "); +} +function locatorOrSelectorAsSelector(language, locator2, testIdAttributeName2 = "data-testid") { + try { + return unsafeLocatorOrSelectorAsSelector(language, locator2, testIdAttributeName2); + } catch (e) { + return ""; + } +} +function unsafeLocatorOrSelectorAsSelector(language, locator2, testIdAttributeName2 = "data-testid") { + try { + parseSelector(locator2); + return locator2; + } catch (e) { + } + const { selector, preferredQuote } = parseLocator(locator2, testIdAttributeName2); + const locators = asLocators(language, selector, void 0, void 0, preferredQuote); + const digest = digestForComparison(language, locator2); + if (locators.some((candidate) => digestForComparison(language, candidate) === digest)) + return selector; + return ""; +} +function digestForComparison(language, locator2) { + locator2 = locator2.replace(/\s/g, ""); + if (language === "javascript") + locator2 = locator2.replace(/\\?["`]/g, "'").replace(/,{}/g, ""); + return locator2; +} +var init_locatorParser = __esm({ + "packages/isomorphic/locatorParser.ts"() { + "use strict"; + init_locatorGenerators(); + init_locatorUtils(); + init_selectorParser(); + init_stringUtils(); + } +}); + +// packages/isomorphic/trace/snapshotRenderer.ts +function findClosest(items, metric, target) { + return items.find((item, index) => { + if (index === items.length - 1) + return true; + const next = items[index + 1]; + return Math.abs(metric(item) - target) < Math.abs(metric(next) - target); + }); +} +function isNodeNameAttributesChildNodesSnapshot(n) { + return Array.isArray(n) && typeof n[0] === "string"; +} +function isSubtreeReferenceSnapshot(n) { + return Array.isArray(n) && Array.isArray(n[0]); +} +function snapshotNodes(snapshot3) { + if (!snapshot3._nodes) { + const nodes = []; + const visit = (n) => { + if (typeof n === "string") { + nodes.push(n); + } else if (isNodeNameAttributesChildNodesSnapshot(n)) { + const [, , ...children] = n; + for (const child of children) + visit(child); + nodes.push(n); + } + }; + visit(snapshot3.html); + snapshot3._nodes = nodes; + } + return snapshot3._nodes; +} +function snapshotScript(viewport, ...targetIds) { + function applyPlaywrightAttributes(blankSnapshotUrl2, viewport2, ...targetIds2) { + const win = window; + const searchParams = new URLSearchParams(win.location.search); + const shouldPopulateCanvasFromScreenshot = searchParams.has("shouldPopulateCanvasFromScreenshot"); + const isUnderTest2 = searchParams.has("isUnderTest"); + const frameBoundingRectsInfo = { + viewport: viewport2, + frames: /* @__PURE__ */ new WeakMap() + }; + win["__playwright_frame_bounding_rects__"] = frameBoundingRectsInfo; + const kPointerWarningTitle = "Recorded click position in absolute coordinates did not match the center of the clicked element. This is either due to the use of provided offset, or due to a difference between the test runner and the trace viewer operating systems."; + const scrollTops = []; + const scrollLefts = []; + const targetElements = []; + const canvasElements = []; + let topSnapshotWindow = win; + while (topSnapshotWindow !== topSnapshotWindow.parent && !topSnapshotWindow.location.pathname.match(/\/page@[a-z0-9]+$/)) + topSnapshotWindow = topSnapshotWindow.parent; + const visit = (root) => { + for (const e of root.querySelectorAll(`[__playwright_scroll_top_]`)) + scrollTops.push(e); + for (const e of root.querySelectorAll(`[__playwright_scroll_left_]`)) + scrollLefts.push(e); + for (const element2 of root.querySelectorAll(`[__playwright_value_]`)) { + const inputElement = element2; + if (inputElement.type !== "file") + inputElement.value = inputElement.getAttribute("__playwright_value_"); + element2.removeAttribute("__playwright_value_"); + } + for (const element2 of root.querySelectorAll(`[__playwright_checked_]`)) { + element2.checked = element2.getAttribute("__playwright_checked_") === "true"; + element2.removeAttribute("__playwright_checked_"); + } + for (const element2 of root.querySelectorAll(`[__playwright_selected_]`)) { + element2.selected = element2.getAttribute("__playwright_selected_") === "true"; + element2.removeAttribute("__playwright_selected_"); + } + for (const element2 of root.querySelectorAll(`[__playwright_popover_open_]`)) { + try { + element2.showPopover(); + } catch { + } + element2.removeAttribute("__playwright_popover_open_"); + } + for (const element2 of root.querySelectorAll(`[__playwright_dialog_open_]`)) { + try { + if (element2.getAttribute("__playwright_dialog_open_") === "modal") + element2.showModal(); + else + element2.show(); + } catch { + } + element2.removeAttribute("__playwright_dialog_open_"); + } + const highlightTarget = (target) => { + const style = target.style; + style.outline = "2px solid #006ab1"; + style.backgroundColor = "#6fa8dc7f"; + targetElements.push(target); + }; + for (const target of root.querySelectorAll(`[__playwright_target__=""]`)) + highlightTarget(target); + for (const targetId of targetIds2) { + if (!targetId) + continue; + for (const target of root.querySelectorAll(`[__playwright_target__="${targetId}"]`)) + highlightTarget(target); + } + for (const iframe of root.querySelectorAll("iframe, frame")) { + const boundingRectJson = iframe.getAttribute("__playwright_bounding_rect__"); + iframe.removeAttribute("__playwright_bounding_rect__"); + const boundingRect = boundingRectJson ? JSON.parse(boundingRectJson) : void 0; + if (boundingRect) + frameBoundingRectsInfo.frames.set(iframe, { boundingRect, scrollLeft: 0, scrollTop: 0 }); + const src = iframe.getAttribute("__playwright_src__"); + if (!src) { + iframe.setAttribute("src", blankSnapshotUrl2); + } else { + const url2 = new URL(win.location.href); + const index = url2.pathname.lastIndexOf("/snapshot/"); + if (index !== -1) + url2.pathname = url2.pathname.substring(0, index + 1); + url2.pathname += src.substring(1); + iframe.setAttribute("src", url2.toString()); + } + } + { + const body = root.querySelector(`body[__playwright_custom_elements__]`); + if (body && win.customElements) { + const customElements = (body.getAttribute("__playwright_custom_elements__") || "").split(","); + for (const elementName of customElements) + win.customElements.define(elementName, class extends HTMLElement { + }); + } + } + for (const element2 of root.querySelectorAll(`template[__playwright_shadow_root_]`)) { + const template = element2; + const shadowRoot = template.parentElement.attachShadow({ mode: "open" }); + shadowRoot.appendChild(template.content); + template.remove(); + visit(shadowRoot); + } + for (const element2 of root.querySelectorAll("a")) + element2.addEventListener("click", (event) => { + event.preventDefault(); + }); + if ("adoptedStyleSheets" in root) { + const adoptedSheets = [...root.adoptedStyleSheets]; + for (const element2 of root.querySelectorAll(`template[__playwright_style_sheet_]`)) { + const template = element2; + const sheet = new CSSStyleSheet(); + sheet.replaceSync(template.getAttribute("__playwright_style_sheet_")); + adoptedSheets.push(sheet); + } + root.adoptedStyleSheets = adoptedSheets; + } + canvasElements.push(...root.querySelectorAll("canvas")); + }; + const onLoad = () => { + win.removeEventListener("load", onLoad); + for (const element2 of scrollTops) { + element2.scrollTop = +element2.getAttribute("__playwright_scroll_top_"); + element2.removeAttribute("__playwright_scroll_top_"); + if (frameBoundingRectsInfo.frames.has(element2)) + frameBoundingRectsInfo.frames.get(element2).scrollTop = element2.scrollTop; + } + for (const element2 of scrollLefts) { + element2.scrollLeft = +element2.getAttribute("__playwright_scroll_left_"); + element2.removeAttribute("__playwright_scroll_left_"); + if (frameBoundingRectsInfo.frames.has(element2)) + frameBoundingRectsInfo.frames.get(element2).scrollLeft = element2.scrollLeft; + } + win.document.styleSheets[0].disabled = true; + const search = new URL(win.location.href).searchParams; + const isTopFrame = win === topSnapshotWindow; + if (isTopFrame && search.get("pointX") && search.get("pointY")) { + const pointX = +search.get("pointX"); + const pointY = +search.get("pointY"); + const pointElement = win.document.createElement("x-pw-pointer"); + pointElement.style.position = "fixed"; + pointElement.style.backgroundColor = "#f44336"; + pointElement.style.width = "20px"; + pointElement.style.height = "20px"; + pointElement.style.borderRadius = "10px"; + pointElement.style.margin = "-10px 0 0 -10px"; + pointElement.style.zIndex = "2147483646"; + pointElement.style.display = "flex"; + pointElement.style.alignItems = "center"; + pointElement.style.justifyContent = "center"; + const target = targetElements[0]; + const targetBox = target?.getBoundingClientRect(); + const targetCenter = target ? { x: targetBox.left + targetBox.width / 2, y: targetBox.top + targetBox.height / 2 } : null; + pointElement.style.left = (targetCenter?.x ?? pointX) + "px"; + pointElement.style.top = (targetCenter?.y ?? pointY) + "px"; + const isAligned = !targetCenter || Math.abs(targetCenter.x - pointX) <= 10 && Math.abs(targetCenter.y - pointY) <= 10; + if (!isAligned) { + const warningElement = win.document.createElement("x-pw-pointer-warning"); + warningElement.textContent = "\u26A0"; + warningElement.style.fontSize = "19px"; + warningElement.style.color = "white"; + warningElement.style.marginTop = "-3.5px"; + warningElement.style.userSelect = "none"; + pointElement.appendChild(warningElement); + pointElement.setAttribute("title", kPointerWarningTitle); + } + win.document.documentElement.appendChild(pointElement); + } + if (canvasElements.length > 0) { + let drawCheckerboard2 = function(context2, canvas) { + function createCheckerboardPattern() { + const pattern = win.document.createElement("canvas"); + pattern.width = pattern.width / Math.floor(pattern.width / 24); + pattern.height = pattern.height / Math.floor(pattern.height / 24); + const context3 = pattern.getContext("2d"); + context3.fillStyle = "lightgray"; + context3.fillRect(0, 0, pattern.width, pattern.height); + context3.fillStyle = "white"; + context3.fillRect(0, 0, pattern.width / 2, pattern.height / 2); + context3.fillRect(pattern.width / 2, pattern.height / 2, pattern.width, pattern.height); + return context3.createPattern(pattern, "repeat"); + } + context2.fillStyle = createCheckerboardPattern(); + context2.fillRect(0, 0, canvas.width, canvas.height); + }; + var drawCheckerboard = drawCheckerboard2; + const img = new Image(); + img.onload = () => { + for (const canvas of canvasElements) { + const context2 = canvas.getContext("2d"); + const boundingRectAttribute = canvas.getAttribute("__playwright_bounding_rect__"); + canvas.removeAttribute("__playwright_bounding_rect__"); + if (!boundingRectAttribute) + continue; + let boundingRect; + try { + boundingRect = JSON.parse(boundingRectAttribute); + } catch (e) { + continue; + } + let currWindow = win; + while (currWindow !== topSnapshotWindow) { + const iframe = currWindow.frameElement; + currWindow = currWindow.parent; + const iframeInfo = currWindow["__playwright_frame_bounding_rects__"]?.frames.get(iframe); + if (!iframeInfo?.boundingRect) + break; + const leftOffset = iframeInfo.boundingRect.left - iframeInfo.scrollLeft; + const topOffset = iframeInfo.boundingRect.top - iframeInfo.scrollTop; + boundingRect.left += leftOffset; + boundingRect.top += topOffset; + boundingRect.right += leftOffset; + boundingRect.bottom += topOffset; + } + const { width, height } = topSnapshotWindow["__playwright_frame_bounding_rects__"].viewport; + boundingRect.left = boundingRect.left / width; + boundingRect.top = boundingRect.top / height; + boundingRect.right = boundingRect.right / width; + boundingRect.bottom = boundingRect.bottom / height; + const partiallyUncaptured = boundingRect.right > 1 || boundingRect.bottom > 1; + const fullyUncaptured = boundingRect.left > 1 || boundingRect.top > 1; + if (fullyUncaptured) { + canvas.title = `Playwright couldn't capture canvas contents because it's located outside the viewport.`; + continue; + } + drawCheckerboard2(context2, canvas); + if (shouldPopulateCanvasFromScreenshot) { + context2.drawImage(img, boundingRect.left * img.width, boundingRect.top * img.height, (boundingRect.right - boundingRect.left) * img.width, (boundingRect.bottom - boundingRect.top) * img.height, 0, 0, canvas.width, canvas.height); + if (partiallyUncaptured) + canvas.title = `Playwright couldn't capture full canvas contents because it's located partially outside the viewport.`; + else + canvas.title = `Canvas contents are displayed on a best-effort basis based on viewport screenshots taken during test execution.`; + } else { + canvas.title = "Canvas content display is disabled."; + } + if (isUnderTest2) + console.log(`canvas drawn:`, JSON.stringify([boundingRect.left, boundingRect.top, boundingRect.right - boundingRect.left, boundingRect.bottom - boundingRect.top].map((v) => Math.floor(v * 100)))); + } + }; + img.onerror = () => { + for (const canvas of canvasElements) { + const context2 = canvas.getContext("2d"); + drawCheckerboard2(context2, canvas); + canvas.title = `Playwright couldn't show canvas contents because the screenshot failed to load.`; + } + }; + img.src = location.href.replace("/snapshot", "/closest-screenshot"); + } + }; + const onDOMContentLoaded = () => visit(win.document); + win.addEventListener("load", onLoad); + win.addEventListener("DOMContentLoaded", onDOMContentLoaded); + } + const safe = (value2) => JSON.stringify(value2).replace(/ `, ${safe(String(id))}`).join("")})`; +} +function rewriteURLForCustomProtocol(href) { + if (href.startsWith(kLegacyBlobPrefix)) + href = href.substring(kLegacyBlobPrefix.length); + try { + const url2 = new URL(href); + if (url2.protocol === "javascript:" || url2.protocol === "vbscript:") + return "javascript:void(0)"; + const isBlob = url2.protocol === "blob:"; + const isFile = url2.protocol === "file:"; + if (!isBlob && !isFile && schemas.includes(url2.protocol)) + return href; + const prefix = "pw-" + url2.protocol.slice(0, url2.protocol.length - 1); + if (!isFile) + url2.protocol = "https:"; + url2.hostname = url2.hostname ? `${prefix}--${url2.hostname}` : prefix; + if (isFile) { + url2.protocol = "https:"; + } + return url2.toString(); + } catch { + return href; + } +} +function rewriteURLsInStyleSheetForCustomProtocol(text2) { + return text2.replace(urlInCSSRegex, (match, protocol) => { + const isBlob = protocol === "blob:"; + const isFile = protocol === "file:"; + if (!isBlob && !isFile && schemas.includes(protocol)) + return match; + return match.replace(protocol + "//", `https://pw-${protocol.slice(0, -1)}--`); + }); +} +function escapeURLsInStyleSheet(text2) { + const replacer = (match, url2) => { + if (url2.includes(" frame.frameSwapWallTime, wallTime) : findClosest(this._screencastFrames, (frame) => frame.timestamp, timestamp); + return closestFrame?.sha1; + } + render() { + const result2 = []; + const visit = (n, snapshotIndex, parentTag, parentAttrs) => { + if (typeof n === "string") { + if (parentTag === "STYLE" || parentTag === "style") + result2.push(escapeURLsInStyleSheet(rewriteURLsInStyleSheetForCustomProtocol(n))); + else + result2.push(escapeHTML(n)); + return; + } + if (isSubtreeReferenceSnapshot(n)) { + const referenceIndex = snapshotIndex - n[0][0]; + if (referenceIndex >= 0 && referenceIndex <= snapshotIndex) { + const nodes = snapshotNodes(this._snapshots[referenceIndex]); + const nodeIndex = n[0][1]; + if (nodeIndex >= 0 && nodeIndex < nodes.length) + return visit(nodes[nodeIndex], referenceIndex, parentTag, parentAttrs); + } + } else if (isNodeNameAttributesChildNodesSnapshot(n)) { + const [name, nodeAttrs, ...children] = n; + if (name.toUpperCase() === "SCRIPT") + return; + const upperName = name.toUpperCase(); + const nodeName = upperName === "NOSCRIPT" ? "X-NOSCRIPT" : name; + const attrs = Object.entries(nodeAttrs || {}); + result2.push("<", nodeName); + const kCurrentSrcAttribute = "__playwright_current_src__"; + const isFrame = upperName === "IFRAME" || upperName === "FRAME"; + const isAnchor = upperName === "A"; + const isImg = upperName === "IMG"; + const isMeta = upperName === "META"; + const isImgWithCurrentSrc = isImg && attrs.some((a) => a[0] === kCurrentSrcAttribute); + const isSourceInsidePictureWithCurrentSrc = upperName === "SOURCE" && parentTag === "PICTURE" && parentAttrs?.some((a) => a[0] === kCurrentSrcAttribute); + const hasUnsafeHttpEquiv = isMeta && attrs.some((a) => a[0].toLowerCase() === "http-equiv" && !kAllowedMetaHttpEquivs.has(a[1].trim().toLowerCase())); + for (const [attr, value2] of attrs) { + let attrName = attr; + if (attr.toLowerCase().startsWith("on")) + continue; + if (isFrame && attr.toLowerCase() === "src") { + attrName = "__playwright_src__"; + } + if (isFrame && (attr.toLowerCase() === "srcdoc" || attr.toLowerCase() === "sandbox")) { + attrName = "__playwright_" + attr.toLowerCase() + "__"; + } + if (upperName === "OBJECT" && attr.toLowerCase() === "data") + attrName = "__playwright_data__"; + if (upperName === "EMBED" && attr.toLowerCase() === "src") + attrName = "__playwright_src__"; + if (isImg && attr === kCurrentSrcAttribute) { + attrName = "src"; + } + if (["src", "srcset"].includes(attr.toLowerCase()) && (isImgWithCurrentSrc || isSourceInsidePictureWithCurrentSrc)) { + attrName = "_" + attrName; + } + if (hasUnsafeHttpEquiv && (attr.toLowerCase() === "http-equiv" || attr.toLowerCase() === "content")) { + attrName = "_" + attr; + } + let attrValue = value2; + if (!isAnchor && (attr.toLowerCase() === "href" || attr.toLowerCase() === "src" || attr === kCurrentSrcAttribute)) + attrValue = rewriteURLForCustomProtocol(value2); + result2.push(" ", attrName, '="', escapeHTMLAttribute(attrValue), '"'); + } + result2.push(">"); + for (const child of children) + visit(child, snapshotIndex, nodeName, attrs); + if (!autoClosing.has(nodeName)) + result2.push(""); + return; + } else { + return; + } + }; + const snapshot3 = this._snapshot; + const html = this._htmlCache.getOrCompute(this, () => { + visit(snapshot3.html, this._index, void 0, void 0); + const safeDoctype = snapshot3.doctype?.replace(/[^a-zA-Z0-9]/g, ""); + const prefix = safeDoctype ? `` : ""; + const html2 = prefix + [ + // Hide the document in order to prevent flickering. We will unhide once script has processed shadow. + "", + `` + ].join("") + result2.join(""); + return { value: html2, size: html2.length }; + }); + return { html, pageId: snapshot3.pageId, frameId: snapshot3.frameId, index: this._index }; + } + resourceByUrl(url2, method) { + const snapshot3 = this._snapshot; + let sameFrameResource; + let otherFrameResource; + for (const resource of this._resources) { + if (typeof resource._monotonicTime === "number" && resource._monotonicTime >= snapshot3.timestamp) + break; + if (resource.response.status === 304) { + continue; + } + if (resource.request.url === url2 && resource.request.method === method) { + if (resource._frameref === snapshot3.frameId) + sameFrameResource = resource; + else + otherFrameResource = resource; + } + } + let result2 = sameFrameResource ?? otherFrameResource; + if (result2 && method.toUpperCase() === "GET") { + let override = snapshot3.resourceOverrides.find((o) => o.url === url2); + if (override?.ref) { + const index = this._index - override.ref; + if (index >= 0 && index < this._snapshots.length) + override = this._snapshots[index].resourceOverrides.find((o) => o.url === url2); + } + if (override?.sha1) { + result2 = { + ...result2, + response: { + ...result2.response, + content: { + ...result2.response.content, + _sha1: override.sha1 + } + } + }; + } + } + return result2; + } + }; + autoClosing = /* @__PURE__ */ new Set(["AREA", "BASE", "BR", "COL", "COMMAND", "EMBED", "HR", "IMG", "INPUT", "KEYGEN", "LINK", "MENUITEM", "META", "PARAM", "SOURCE", "TRACK", "WBR"]); + kAllowedMetaHttpEquivs = /* @__PURE__ */ new Set(["content-type", "content-language", "default-style", "x-ua-compatible"]); + schemas = ["about:", "blob:", "data:", "file:", "ftp:", "http:", "https:", "mailto:", "sftp:", "ws:", "wss:"]; + kLegacyBlobPrefix = "http://playwright.bloburl/#"; + urlInCSSRegex = /url\(['"]?([\w-]+:)\/\//ig; + urlToEscapeRegex1 = /url\(\s*'([^']*)'\s*\)/ig; + urlToEscapeRegex2 = /url\(\s*"([^"]*)"\s*\)/ig; + blankSnapshotUrl = "data:text/html;base64," + btoa(``); + } +}); + +// packages/isomorphic/lruCache.ts +var LRUCache; +var init_lruCache = __esm({ + "packages/isomorphic/lruCache.ts"() { + "use strict"; + LRUCache = class { + constructor(maxSize) { + this._maxSize = maxSize; + this._map = /* @__PURE__ */ new Map(); + this._size = 0; + } + getOrCompute(key, compute) { + if (this._map.has(key)) { + const result3 = this._map.get(key); + this._map.delete(key); + this._map.set(key, result3); + return result3.value; + } + const result2 = compute(); + while (this._map.size && this._size + result2.size > this._maxSize) { + const [firstKey, firstValue] = this._map.entries().next().value; + this._size -= firstValue.size; + this._map.delete(firstKey); + } + this._map.set(key, result2); + this._size += result2.size; + return result2.value; + } + }; + } +}); + +// packages/isomorphic/trace/snapshotStorage.ts +var SnapshotStorage; +var init_snapshotStorage = __esm({ + "packages/isomorphic/trace/snapshotStorage.ts"() { + "use strict"; + init_snapshotRenderer(); + init_lruCache(); + SnapshotStorage = class { + constructor() { + this._frameSnapshots = /* @__PURE__ */ new Map(); + this._cache = new LRUCache(1e8); + // 100MB per each trace + this._contextToResources = /* @__PURE__ */ new Map(); + this._resourceUrlsWithOverrides = /* @__PURE__ */ new Set(); + } + addResource(contextId4, resource) { + resource.request.url = rewriteURLForCustomProtocol(resource.request.url); + this._ensureResourcesForContext(contextId4).push(resource); + } + addFrameSnapshot(contextId4, snapshot3, screencastFrames) { + for (const override of snapshot3.resourceOverrides) + override.url = rewriteURLForCustomProtocol(override.url); + let frameSnapshots = this._frameSnapshots.get(snapshot3.frameId); + if (!frameSnapshots) { + frameSnapshots = { + raw: [], + renderers: [] + }; + this._frameSnapshots.set(snapshot3.frameId, frameSnapshots); + if (snapshot3.isMainFrame) + this._frameSnapshots.set(snapshot3.pageId, frameSnapshots); + } + frameSnapshots.raw.push(snapshot3); + const resources = this._ensureResourcesForContext(contextId4); + const renderer = new SnapshotRenderer(this._cache, resources, frameSnapshots.raw, screencastFrames, frameSnapshots.raw.length - 1); + frameSnapshots.renderers.push(renderer); + return renderer; + } + snapshotByName(pageOrFrameId, snapshotName) { + const snapshot3 = this._frameSnapshots.get(pageOrFrameId); + return snapshot3?.renderers.find((r) => r.snapshotName === snapshotName); + } + snapshotsForTest() { + return [...this._frameSnapshots.keys()]; + } + finalize() { + for (const resources of this._contextToResources.values()) + resources.sort((a, b) => (a._monotonicTime || 0) - (b._monotonicTime || 0)); + for (const frameSnapshots of this._frameSnapshots.values()) { + for (const snapshot3 of frameSnapshots.raw) { + for (const override of snapshot3.resourceOverrides) + this._resourceUrlsWithOverrides.add(override.url); + } + } + } + hasResourceOverride(url2) { + return this._resourceUrlsWithOverrides.has(url2); + } + _ensureResourcesForContext(contextId4) { + let resources = this._contextToResources.get(contextId4); + if (!resources) { + resources = []; + this._contextToResources.set(contextId4, resources); + } + return resources; + } + }; + } +}); + +// packages/isomorphic/trace/traceUtils.ts +function parseClientSideCallMetadata(data) { + const result2 = /* @__PURE__ */ new Map(); + const { files, stacks } = data; + for (const s of stacks) { + const [id, ff] = s; + result2.set(`call@${id}`, ff.map((f) => ({ file: files[f[0]], line: f[1], column: f[2], function: f[3] }))); + } + return result2; +} +function serializeClientSideCallMetadata(metadatas) { + const fileNames = /* @__PURE__ */ new Map(); + const stacks = []; + for (const m of metadatas) { + if (!m.stack || !m.stack.length) + continue; + const stack = []; + for (const frame of m.stack) { + let ordinal = fileNames.get(frame.file); + if (typeof ordinal !== "number") { + ordinal = fileNames.size; + fileNames.set(frame.file, ordinal); + } + const stackFrame = [ordinal, frame.line || 0, frame.column || 0, frame.function || ""]; + stack.push(stackFrame); + } + stacks.push([m.id, stack]); + } + return { files: [...fileNames.keys()], stacks }; +} +var init_traceUtils = __esm({ + "packages/isomorphic/trace/traceUtils.ts"() { + "use strict"; + } +}); + +// packages/isomorphic/trace/traceModernizer.ts +var TraceVersionError, latestVersion, TraceModernizer; +var init_traceModernizer = __esm({ + "packages/isomorphic/trace/traceModernizer.ts"() { + "use strict"; + TraceVersionError = class extends Error { + constructor(message) { + super(message); + this.name = "TraceVersionError"; + } + }; + latestVersion = 8; + TraceModernizer = class { + constructor(contextEntry, snapshotStorage) { + this._actionMap = /* @__PURE__ */ new Map(); + this._pageEntries = /* @__PURE__ */ new Map(); + this._jsHandles = /* @__PURE__ */ new Map(); + this._consoleObjects = /* @__PURE__ */ new Map(); + this._contextEntry = contextEntry; + this._snapshotStorage = snapshotStorage; + } + appendTrace(trace) { + for (const line of trace.split("\n")) + this._appendEvent(line); + } + actions() { + return [...this._actionMap.values()]; + } + _pageEntry(pageId4) { + let pageEntry = this._pageEntries.get(pageId4); + if (!pageEntry) { + pageEntry = { + pageId: pageId4, + screencastFrames: [] + }; + this._pageEntries.set(pageId4, pageEntry); + this._contextEntry.pages.push(pageEntry); + } + return pageEntry; + } + _appendEvent(line) { + if (!line) + return; + const events = this._modernize(JSON.parse(line)); + for (const event of events) + this._innerAppendEvent(event); + } + _innerAppendEvent(event) { + const contextEntry = this._contextEntry; + switch (event.type) { + case "context-options": { + if (event.version > latestVersion) + throw new TraceVersionError("The trace was created by a newer version of Playwright and is not supported by this version of the viewer. Please use latest Playwright to open the trace."); + this._version = event.version; + contextEntry.origin = event.origin; + contextEntry.browserName = event.browserName; + contextEntry.channel = event.channel; + contextEntry.title = event.title; + contextEntry.platform = event.platform; + contextEntry.playwrightVersion = event.playwrightVersion; + contextEntry.wallTime = event.wallTime; + contextEntry.startTime = event.monotonicTime; + contextEntry.sdkLanguage = event.sdkLanguage; + contextEntry.options = event.options; + contextEntry.testIdAttributeName = event.testIdAttributeName; + contextEntry.contextId = event.contextId ?? ""; + contextEntry.testTimeout = event.testTimeout; + break; + } + case "screencast-frame": { + this._pageEntry(event.pageId).screencastFrames.push(event); + break; + } + case "before": { + this._actionMap.set(event.callId, { ...event, type: "action", endTime: 0, log: [] }); + break; + } + case "input": { + const existing = this._actionMap.get(event.callId); + existing.inputSnapshot = event.inputSnapshot; + existing.point = event.point; + break; + } + case "log": { + const existing = this._actionMap.get(event.callId); + if (!existing) + return; + existing.log.push({ + time: event.time, + message: event.message + }); + break; + } + case "after": { + const existing = this._actionMap.get(event.callId); + existing.afterSnapshot = event.afterSnapshot; + existing.endTime = event.endTime; + existing.result = event.result; + existing.error = event.error; + existing.attachments = event.attachments; + existing.annotations = event.annotations; + if (event.point) + existing.point = event.point; + break; + } + case "action": { + this._actionMap.set(event.callId, { ...event, log: [] }); + break; + } + case "event": { + contextEntry.events.push(event); + break; + } + case "stdout": { + contextEntry.stdio.push(event); + break; + } + case "stderr": { + contextEntry.stdio.push(event); + break; + } + case "error": { + contextEntry.errors.push(event); + break; + } + case "console": { + contextEntry.events.push(event); + break; + } + case "resource-snapshot": + this._snapshotStorage.addResource(this._contextEntry.contextId, event.snapshot); + contextEntry.resources.push(event.snapshot); + break; + case "frame-snapshot": + this._snapshotStorage.addFrameSnapshot(this._contextEntry.contextId, event.snapshot, this._pageEntry(event.snapshot.pageId).screencastFrames); + break; + } + if ("pageId" in event && event.pageId) + this._pageEntry(event.pageId); + if (event.type === "action" || event.type === "before") + contextEntry.startTime = Math.min(contextEntry.startTime, event.startTime); + if (event.type === "action" || event.type === "after") + contextEntry.endTime = Math.max(contextEntry.endTime, event.endTime); + if (event.type === "event") { + contextEntry.startTime = Math.min(contextEntry.startTime, event.time); + contextEntry.endTime = Math.max(contextEntry.endTime, event.time); + } + if (event.type === "screencast-frame") { + contextEntry.startTime = Math.min(contextEntry.startTime, event.timestamp); + contextEntry.endTime = Math.max(contextEntry.endTime, event.timestamp); + } + } + _processedContextCreatedEvent() { + return this._version !== void 0; + } + _modernize(event) { + let version3 = this._version ?? event.version ?? 6; + let events = [event]; + for (; version3 < latestVersion; ++version3) + events = this[`_modernize_${version3}_to_${version3 + 1}`].call(this, events); + return events; + } + _modernize_0_to_1(events) { + for (const event of events) { + if (event.type !== "action") + continue; + if (typeof event.metadata.error === "string") + event.metadata.error = { error: { name: "Error", message: event.metadata.error } }; + } + return events; + } + _modernize_1_to_2(events) { + for (const event of events) { + if (event.type !== "frame-snapshot" || !event.snapshot.isMainFrame) + continue; + event.snapshot.viewport = this._contextEntry.options?.viewport || { width: 1280, height: 720 }; + } + return events; + } + _modernize_2_to_3(events) { + for (const event of events) { + if (event.type !== "resource-snapshot" || event.snapshot.request) + continue; + const resource = event.snapshot; + event.snapshot = { + _frameref: resource.frameId, + request: { + url: resource.url, + method: resource.method, + headers: resource.requestHeaders, + postData: resource.requestSha1 ? { _sha1: resource.requestSha1 } : void 0 + }, + response: { + status: resource.status, + headers: resource.responseHeaders, + content: { + mimeType: resource.contentType, + _sha1: resource.responseSha1 + } + }, + _monotonicTime: resource.timestamp + }; + } + return events; + } + _modernize_3_to_4(events) { + const result2 = []; + for (const event of events) { + const e = this._modernize_event_3_to_4(event); + if (e) + result2.push(e); + } + return result2; + } + _modernize_event_3_to_4(event) { + if (event.type !== "action" && event.type !== "event") { + return event; + } + const metadata = event.metadata; + if (metadata.internal || metadata.method.startsWith("tracing")) + return null; + if (event.type === "event") { + if (metadata.method === "__create__" && metadata.type === "ConsoleMessage") { + return { + type: "object", + class: metadata.type, + guid: metadata.params.guid, + initializer: metadata.params.initializer + }; + } + return { + type: "event", + time: metadata.startTime, + class: metadata.type, + method: metadata.method, + params: metadata.params, + pageId: metadata.pageId + }; + } + return { + type: "action", + callId: metadata.id, + startTime: metadata.startTime, + endTime: metadata.endTime, + apiName: metadata.apiName || metadata.type + "." + metadata.method, + class: metadata.type, + method: metadata.method, + params: metadata.params, + // eslint-disable-next-line no-restricted-globals + wallTime: metadata.wallTime || Date.now(), + log: metadata.log, + beforeSnapshot: metadata.snapshots.find((s) => s.title === "before")?.snapshotName, + inputSnapshot: metadata.snapshots.find((s) => s.title === "input")?.snapshotName, + afterSnapshot: metadata.snapshots.find((s) => s.title === "after")?.snapshotName, + error: metadata.error?.error, + result: metadata.result, + point: metadata.point, + pageId: metadata.pageId + }; + } + _modernize_4_to_5(events) { + const result2 = []; + for (const event of events) { + const e = this._modernize_event_4_to_5(event); + if (e) + result2.push(e); + } + return result2; + } + _modernize_event_4_to_5(event) { + if (event.type === "event" && event.method === "__create__" && event.class === "JSHandle") + this._jsHandles.set(event.params.guid, event.params.initializer); + if (event.type === "object") { + if (event.class !== "ConsoleMessage") + return null; + const args = event.initializer.args?.map((arg) => { + if (arg.guid) { + const handle = this._jsHandles.get(arg.guid); + return { preview: handle?.preview || "", value: "" }; + } + return { preview: arg.preview || "", value: arg.value || "" }; + }); + this._consoleObjects.set(event.guid, { + type: event.initializer.type, + text: event.initializer.text, + location: event.initializer.location, + args + }); + return null; + } + if (event.type === "event" && event.method === "console") { + const consoleMessage = this._consoleObjects.get(event.params.message?.guid || ""); + if (!consoleMessage) + return null; + return { + type: "console", + time: event.time, + pageId: event.pageId, + messageType: consoleMessage.type, + text: consoleMessage.text, + args: consoleMessage.args, + location: consoleMessage.location + }; + } + return event; + } + _modernize_5_to_6(events) { + const result2 = []; + for (const event of events) { + result2.push(event); + if (event.type !== "after" || !event.log.length) + continue; + for (const log2 of event.log) { + result2.push({ + type: "log", + callId: event.callId, + message: log2, + time: -1 + }); + } + } + return result2; + } + _modernize_6_to_7(events) { + const result2 = []; + if (!this._processedContextCreatedEvent() && events[0].type !== "context-options") { + const event = { + type: "context-options", + origin: "testRunner", + version: 6, + browserName: "", + options: {}, + platform: "unknown", + wallTime: 0, + monotonicTime: 0, + sdkLanguage: "javascript", + contextId: "" + }; + result2.push(event); + } + for (const event of events) { + if (event.type === "context-options") { + result2.push({ ...event, monotonicTime: 0, origin: "library", contextId: "" }); + continue; + } + if (event.type === "before" || event.type === "action") { + if (!this._contextEntry.wallTime) + this._contextEntry.wallTime = event.wallTime; + const eventAsV6 = event; + const eventAsV7 = event; + eventAsV7.stepId = `${eventAsV6.apiName}@${eventAsV6.wallTime}`; + result2.push(eventAsV7); + } else { + result2.push(event); + } + } + return result2; + } + _modernize_7_to_8(events) { + const result2 = []; + for (const event of events) { + if (event.type === "before" || event.type === "action") { + const eventAsV7 = event; + const eventAsV8 = event; + if (eventAsV7.apiName) { + eventAsV8.title = eventAsV7.apiName; + delete eventAsV8.apiName; + } + eventAsV8.stepId = eventAsV7.stepId ?? eventAsV7.callId; + result2.push(eventAsV8); + } else { + result2.push(event); + } + } + return result2; + } + }; + } +}); + +// packages/isomorphic/trace/traceLoader.ts +function stripEncodingFromContentType(contentType) { + const charset = contentType.match(/^(.*);\s*charset=.*$/); + if (charset) + return charset[1]; + return contentType; +} +function createEmptyContext() { + return { + origin: "testRunner", + startTime: Number.MAX_SAFE_INTEGER, + wallTime: Number.MAX_SAFE_INTEGER, + endTime: 0, + browserName: "", + options: { + deviceScaleFactor: 1, + isMobile: false, + viewport: { width: 1280, height: 800 } + }, + pages: [], + resources: [], + actions: [], + events: [], + errors: [], + stdio: [], + hasSource: false, + contextId: "" + }; +} +var TraceLoader; +var init_traceLoader = __esm({ + "packages/isomorphic/trace/traceLoader.ts"() { + "use strict"; + init_traceUtils(); + init_snapshotStorage(); + init_traceModernizer(); + TraceLoader = class { + constructor() { + this.contextEntries = []; + this._resourceToContentType = /* @__PURE__ */ new Map(); + } + async load(backend, traceFile, unzipProgress) { + this._backend = backend; + const prefix = traceFile?.match(/(.+)\.trace$/)?.[1]; + const prefixes = []; + let hasSource = false; + for (const entryName of await this._backend.entryNames()) { + const match = entryName.match(/(.+)\.trace$/); + if (match && (!prefix || prefix === match[1])) + prefixes.push(match[1] || ""); + if (entryName.includes("src@")) + hasSource = true; + } + if (!prefixes.length) + throw new Error("Cannot find .trace file"); + this._snapshotStorage = new SnapshotStorage(); + const total = prefixes.length * 3; + let done = 0; + for (const prefix2 of prefixes) { + const contextEntry = createEmptyContext(); + contextEntry.hasSource = hasSource; + const modernizer = new TraceModernizer(contextEntry, this._snapshotStorage); + const trace = await this._backend.readText(prefix2 + ".trace") || ""; + modernizer.appendTrace(trace); + unzipProgress?.(++done, total); + const network = await this._backend.readText(prefix2 + ".network") || ""; + modernizer.appendTrace(network); + unzipProgress?.(++done, total); + contextEntry.actions = modernizer.actions().sort((a1, a2) => a1.startTime - a2.startTime); + if (!backend.isLive()) { + for (const action of contextEntry.actions.slice().reverse()) { + if (!action.endTime && !action.error) { + for (const a of contextEntry.actions) { + if (a.parentId === action.callId && action.endTime < a.endTime) + action.endTime = a.endTime; + } + } + } + } + const stacks = await this._backend.readText(prefix2 + ".stacks"); + if (stacks) { + const callMetadata = parseClientSideCallMetadata(JSON.parse(stacks)); + for (const action of contextEntry.actions) + action.stack = action.stack || callMetadata.get(action.callId); + } + unzipProgress?.(++done, total); + for (const resource of contextEntry.resources) { + if (resource.request.postData?._sha1) + this._resourceToContentType.set(resource.request.postData._sha1, stripEncodingFromContentType(resource.request.postData.mimeType)); + if (resource.response.content?._sha1) + this._resourceToContentType.set(resource.response.content._sha1, stripEncodingFromContentType(resource.response.content.mimeType)); + } + this.contextEntries.push(contextEntry); + } + this._snapshotStorage.finalize(); + } + async hasEntry(filename) { + return this._backend.hasEntry(filename); + } + async resourceForSha1(sha1) { + const blob = await this._backend.readBlob("resources/" + sha1); + const contentType = this._resourceToContentType.get(sha1); + if (!blob || contentType === void 0 || contentType === "x-unknown") + return blob; + return new Blob([blob], { type: contentType }); + } + storage() { + return this._snapshotStorage; + } + }; + } +}); + +// packages/isomorphic/trace/traceModel.ts +function indexModel(context2) { + for (const page of context2.pages) + page[contextSymbol] = context2; + for (let i = 0; i < context2.actions.length; ++i) { + const action = context2.actions[i]; + action[contextSymbol] = context2; + } + let lastNonRouteAction = void 0; + for (let i = context2.actions.length - 1; i >= 0; i--) { + const action = context2.actions[i]; + action[nextInContextSymbol] = lastNonRouteAction; + if (action.class !== "Route") + lastNonRouteAction = action; + } + for (const event of context2.events) + event[contextSymbol] = context2; + for (const resource of context2.resources) + resource[contextSymbol] = context2; +} +function mergeActionsAndUpdateTiming(contexts) { + const result2 = []; + const actions = mergeActionsAndUpdateTimingSameTrace(contexts); + result2.push(...actions); + result2.sort((a1, a2) => { + if (a2.parentId === a1.callId) + return 1; + if (a1.parentId === a2.callId) + return -1; + return a1.endTime - a2.endTime; + }); + for (let i = 1; i < result2.length; ++i) + result2[i][prevByEndTimeSymbol] = result2[i - 1]; + result2.sort((a1, a2) => { + if (a2.parentId === a1.callId) + return -1; + if (a1.parentId === a2.callId) + return 1; + return a1.startTime - a2.startTime; + }); + for (let i = 0; i + 1 < result2.length; ++i) + result2[i][nextByStartTimeSymbol] = result2[i + 1]; + return result2; +} +function mergeActionsAndUpdateTimingSameTrace(contexts) { + const map = /* @__PURE__ */ new Map(); + const libraryContexts = contexts.filter((context2) => context2.origin === "library"); + const testRunnerContexts = contexts.filter((context2) => context2.origin === "testRunner"); + if (!testRunnerContexts.length || !libraryContexts.length) { + return contexts.map((context2) => { + return context2.actions.map((action) => ({ ...action, context: context2 })); + }).flat(); + } + for (const context2 of libraryContexts) { + for (const action of context2.actions) { + map.set(action.stepId || `tmp-step@${++lastTmpStepId}`, { ...action, context: context2 }); + } + } + const delta = monotonicTimeDeltaBetweenLibraryAndRunner(testRunnerContexts, map); + if (delta) + adjustMonotonicTime(libraryContexts, delta); + const nonPrimaryIdToPrimaryId = /* @__PURE__ */ new Map(); + for (const context2 of testRunnerContexts) { + for (const action of context2.actions) { + const existing = action.stepId && map.get(action.stepId); + if (existing) { + nonPrimaryIdToPrimaryId.set(action.callId, existing.callId); + if (action.error) + existing.error = action.error; + if (action.attachments) + existing.attachments = action.attachments; + if (action.annotations) + existing.annotations = action.annotations; + if (action.parentId) + existing.parentId = nonPrimaryIdToPrimaryId.get(action.parentId) ?? action.parentId; + if (action.group) + existing.group = action.group; + existing.startTime = action.startTime; + existing.endTime = action.endTime; + continue; + } + if (action.parentId) + action.parentId = nonPrimaryIdToPrimaryId.get(action.parentId) ?? action.parentId; + map.set(action.stepId || `tmp-step@${++lastTmpStepId}`, { ...action, context: context2 }); + } + } + return [...map.values()]; +} +function adjustMonotonicTime(contexts, monotonicTimeDelta) { + for (const context2 of contexts) { + context2.startTime += monotonicTimeDelta; + context2.endTime += monotonicTimeDelta; + for (const action of context2.actions) { + if (action.startTime) + action.startTime += monotonicTimeDelta; + if (action.endTime) + action.endTime += monotonicTimeDelta; + } + for (const event of context2.events) + event.time += monotonicTimeDelta; + for (const event of context2.stdio) + event.timestamp += monotonicTimeDelta; + for (const page of context2.pages) { + for (const frame of page.screencastFrames) + frame.timestamp += monotonicTimeDelta; + } + for (const resource of context2.resources) { + if (resource._monotonicTime) + resource._monotonicTime += monotonicTimeDelta; + } + } +} +function monotonicTimeDeltaBetweenLibraryAndRunner(nonPrimaryContexts, libraryActions) { + for (const context2 of nonPrimaryContexts) { + for (const action of context2.actions) { + if (!action.startTime) + continue; + const libraryAction = action.stepId ? libraryActions.get(action.stepId) : void 0; + if (libraryAction) + return action.startTime - libraryAction.startTime; + } + } + return 0; +} +function buildActionTree(actions) { + const itemMap = /* @__PURE__ */ new Map(); + for (const action of actions) { + itemMap.set(action.callId, { + id: action.callId, + parent: void 0, + children: [], + action + }); + } + const rootItem = { action: { ...kFakeRootAction }, id: "", parent: void 0, children: [] }; + for (const item of itemMap.values()) { + rootItem.action.startTime = Math.min(rootItem.action.startTime, item.action.startTime); + rootItem.action.endTime = Math.max(rootItem.action.endTime, item.action.endTime); + const parent = item.action.parentId ? itemMap.get(item.action.parentId) || rootItem : rootItem; + parent.children.push(item); + item.parent = parent; + } + const inheritStack = (item) => { + for (const child of item.children) { + child.action.stack = child.action.stack ?? item.action.stack; + inheritStack(child); + } + }; + inheritStack(rootItem); + return { rootItem, itemMap }; +} +function context(action) { + return action[contextSymbol]; +} +function nextInContext(action) { + return action[nextInContextSymbol]; +} +function previousActionByEndTime(action) { + return action[prevByEndTimeSymbol]; +} +function nextActionByStartTime(action) { + return action[nextByStartTimeSymbol]; +} +function stats(action) { + let errors = 0; + let warnings = 0; + for (const event of eventsForAction(action)) { + if (event.type === "console") { + const type3 = event.messageType; + if (type3 === "warning") + ++warnings; + else if (type3 === "error") + ++errors; + } + if (event.type === "event" && event.method === "pageError") + ++errors; + } + return { errors, warnings }; +} +function eventsForAction(action) { + let result2 = action[eventsSymbol]; + if (result2) + return result2; + const nextAction = nextInContext(action); + result2 = context(action).events.filter((event) => { + return event.time >= action.startTime && (!nextAction || event.time < nextAction.startTime); + }); + action[eventsSymbol] = result2; + return result2; +} +function collectSources(actions, errorDescriptors) { + const result2 = /* @__PURE__ */ new Map(); + for (const action of actions) { + for (const frame of action.stack || []) { + let source11 = result2.get(frame.file); + if (!source11) { + source11 = { errors: [], content: void 0 }; + result2.set(frame.file, source11); + } + } + } + for (const error of errorDescriptors) { + const { action, stack, message } = error; + if (!action || !stack) + continue; + result2.get(stack[0].file)?.errors.push({ + line: stack[0].line || 0, + message + }); + } + return result2; +} +var contextSymbol, nextInContextSymbol, prevByEndTimeSymbol, nextByStartTimeSymbol, eventsSymbol, TraceModel, lastTmpStepId, kFakeRootAction; +var init_traceModel = __esm({ + "packages/isomorphic/trace/traceModel.ts"() { + "use strict"; + init_protocolFormatter(); + contextSymbol = Symbol("context"); + nextInContextSymbol = Symbol("nextInContext"); + prevByEndTimeSymbol = Symbol("prevByEndTime"); + nextByStartTimeSymbol = Symbol("nextByStartTime"); + eventsSymbol = Symbol("events"); + TraceModel = class { + constructor(traceUri, contexts) { + contexts.forEach((contextEntry) => indexModel(contextEntry)); + const libraryContext = contexts.find((context2) => context2.origin === "library"); + this.traceUri = traceUri; + this.browserName = libraryContext?.browserName || ""; + this.sdkLanguage = libraryContext?.sdkLanguage; + this.channel = libraryContext?.channel; + this.testIdAttributeName = libraryContext?.testIdAttributeName; + this.platform = libraryContext?.platform || ""; + this.playwrightVersion = contexts.find((c) => c.playwrightVersion)?.playwrightVersion; + this.title = libraryContext?.title || ""; + this.options = libraryContext?.options || {}; + this.testTimeout = contexts.find((c) => c.origin === "testRunner")?.testTimeout; + this.actions = mergeActionsAndUpdateTiming(contexts); + this.pages = [].concat(...contexts.map((c) => c.pages)); + this.wallTime = contexts.map((c) => c.wallTime).reduce((prev, cur) => Math.min(prev || Number.MAX_VALUE, cur), Number.MAX_VALUE); + this.startTime = contexts.map((c) => c.startTime).reduce((prev, cur) => Math.min(prev, cur), Number.MAX_VALUE); + this.endTime = contexts.map((c) => c.endTime).reduce((prev, cur) => Math.max(prev, cur), Number.MIN_VALUE); + this.events = [].concat(...contexts.map((c) => c.events)); + this.stdio = [].concat(...contexts.map((c) => c.stdio)); + this.errors = [].concat(...contexts.map((c) => c.errors)); + this.hasSource = contexts.some((c) => c.hasSource); + this.hasStepData = contexts.some((context2) => context2.origin === "testRunner"); + this.resources = [...contexts.map((c) => c.resources)].flat().map((entry) => ({ ...entry, id: `${entry.pageref}-${entry.startedDateTime}-${entry.request.url}` })); + this.attachments = this.actions.flatMap((action) => action.attachments?.map((attachment) => ({ ...attachment, callId: action.callId, traceUri })) ?? []); + this.visibleAttachments = this.attachments.filter((attachment) => !attachment.name.startsWith("_")); + this.events.sort((a1, a2) => a1.time - a2.time); + this.resources.sort((a1, a2) => a1._monotonicTime - a2._monotonicTime); + this.errorDescriptors = this.hasStepData ? this._errorDescriptorsFromTestRunner() : this._errorDescriptorsFromActions(); + this.sources = collectSources(this.actions, this.errorDescriptors); + this.actionCounters = /* @__PURE__ */ new Map(); + for (const action of this.actions) { + action.group = action.group ?? getActionGroup({ type: action.class, method: action.method }); + if (action.group) + this.actionCounters.set(action.group, 1 + (this.actionCounters.get(action.group) || 0)); + } + } + createRelativeUrl(path59) { + const url2 = new URL("http://localhost/" + path59); + url2.searchParams.set("trace", this.traceUri); + return url2.toString().substring("http://localhost/".length); + } + failedAction() { + return this.actions.findLast((a) => a.error); + } + filteredActions(actionsFilter) { + const filter = new Set(actionsFilter); + return this.actions.filter((action) => !action.group || filter.has(action.group)); + } + renderActionTree(filter) { + const actions = this.filteredActions(filter ?? []); + const { rootItem } = buildActionTree(actions); + const actionTree = []; + const visit = (actionItem, indent) => { + const title = renderTitleForCall({ ...actionItem.action, type: actionItem.action.class }); + actionTree.push(`${indent}${title || actionItem.id}`); + for (const child of actionItem.children) + visit(child, indent + " "); + }; + rootItem.children.forEach((a) => visit(a, "")); + return actionTree; + } + _errorDescriptorsFromActions() { + const errors = []; + for (const action of this.actions || []) { + if (!action.error?.message) + continue; + errors.push({ + action, + stack: action.stack, + message: action.error.message + }); + } + return errors; + } + _errorDescriptorsFromTestRunner() { + return this.errors.filter((e) => !!e.message).map((error, i) => ({ + stack: error.stack, + message: error.message + })); + } + }; + lastTmpStepId = 0; + kFakeRootAction = { + type: "action", + callId: "", + startTime: 0, + endTime: 0, + class: "", + method: "", + params: {}, + log: [], + context: { + origin: "library", + startTime: 0, + endTime: 0, + browserName: "", + wallTime: 0, + options: {}, + pages: [], + resources: [], + actions: [], + events: [], + stdio: [], + errors: [], + hasSource: false, + contextId: "" + } + }; + } +}); + +// packages/isomorphic/yaml.ts +function yamlEscapeKeyIfNeeded(str) { + if (!yamlStringNeedsQuotes(str)) + return str; + return `'` + str.replace(/'/g, `''`) + `'`; +} +function yamlEscapeValueIfNeeded(str) { + if (!yamlStringNeedsQuotes(str)) + return str; + return '"' + str.replace(/[\\"\x00-\x1f\x7f-\x9f]/g, (c) => { + switch (c) { + case "\\": + return "\\\\"; + case '"': + return '\\"'; + case "\b": + return "\\b"; + case "\f": + return "\\f"; + case "\n": + return "\\n"; + case "\r": + return "\\r"; + case " ": + return "\\t"; + default: + const code = c.charCodeAt(0); + return "\\x" + code.toString(16).padStart(2, "0"); + } + }) + '"'; +} +function yamlStringNeedsQuotes(str) { + if (str.length === 0) + return true; + if (/^\s|\s$/.test(str)) + return true; + if (/[\x00-\x08\x0b\x0c\x0e-\x1f\x7f-\x9f]/.test(str)) + return true; + if (/^-/.test(str)) + return true; + if (/[\n:](\s|$)/.test(str)) + return true; + if (/\s#/.test(str)) + return true; + if (/[\n\r]/.test(str)) + return true; + if (/^[&*\],?!>|@"'#%]/.test(str)) + return true; + if (/[{}`]/.test(str)) + return true; + if (/^\[/.test(str)) + return true; + if (!isNaN(Number(str)) || ["y", "n", "yes", "no", "true", "false", "on", "off", "null"].includes(str.toLowerCase())) + return true; + return false; +} +var init_yaml = __esm({ + "packages/isomorphic/yaml.ts"() { + "use strict"; + } +}); + +// packages/isomorphic/index.ts +var isomorphic_exports = {}; +__export(isomorphic_exports, { + CSharpLocatorFactory: () => CSharpLocatorFactory, + DEFAULT_PLAYWRIGHT_LAUNCH_TIMEOUT: () => DEFAULT_PLAYWRIGHT_LAUNCH_TIMEOUT, + DEFAULT_PLAYWRIGHT_TIMEOUT: () => DEFAULT_PLAYWRIGHT_TIMEOUT, + InvalidSelectorError: () => InvalidSelectorError, + JavaLocatorFactory: () => JavaLocatorFactory, + JavaScriptLocatorFactory: () => JavaScriptLocatorFactory, + JsonlLocatorFactory: () => JsonlLocatorFactory, + KeyParser: () => KeyParser, + LongStandingScope: () => LongStandingScope, + ManualPromise: () => ManualPromise, + MultiMap: () => MultiMap, + ParserError: () => ParserError, + PythonLocatorFactory: () => PythonLocatorFactory, + Semaphore: () => Semaphore, + SnapshotServer: () => SnapshotServer, + SnapshotStorage: () => SnapshotStorage, + TraceLoader: () => TraceLoader, + TraceModel: () => TraceModel, + ansiRegex: () => ansiRegex, + ariaNodesEqual: () => ariaNodesEqual, + asLocator: () => asLocator, + asLocatorDescription: () => asLocatorDescription, + asLocators: () => asLocators, + assert: () => assert, + base64ByteLength: () => base64ByteLength, + buildActionTree: () => buildActionTree, + bytesToString: () => bytesToString, + cacheNormalizedWhitespaces: () => cacheNormalizedWhitespaces, + captureRawStack: () => captureRawStack, + constructURLBasedOnBaseURL: () => constructURLBasedOnBaseURL, + context: () => context, + customCSSNames: () => customCSSNames, + deserializeURLMatch: () => deserializeURLMatch, + escapeForAttributeSelector: () => escapeForAttributeSelector, + escapeForTextSelector: () => escapeForTextSelector, + escapeHTML: () => escapeHTML, + escapeHTMLAttribute: () => escapeHTMLAttribute, + escapeRegExp: () => escapeRegExp, + escapeTemplateString: () => escapeTemplateString, + escapeWithQuotes: () => escapeWithQuotes, + eventsForAction: () => eventsForAction, + findNewNode: () => findNewNode, + formatObject: () => formatObject, + formatObjectOrVoid: () => formatObjectOrVoid, + formatProtocolParam: () => formatProtocolParam, + getActionGroup: () => getActionGroup, + getExtensionForMimeType: () => getExtensionForMimeType, + getMetainfo: () => getMetainfo, + getMimeTypeForPath: () => getMimeTypeForPath, + globToRegexPattern: () => globToRegexPattern, + hasPointerCursor: () => hasPointerCursor, + headersArrayToObject: () => headersArrayToObject, + headersObjectToArray: () => headersObjectToArray, + isError: () => isError, + isHttpUrl: () => isHttpUrl, + isInvalidSelectorError: () => isInvalidSelectorError, + isJsonMimeType: () => isJsonMimeType, + isObject: () => isObject, + isRegExp: () => isRegExp, + isRegexString: () => isRegexString, + isString: () => isString, + isTextualMimeType: () => isTextualMimeType, + isURLPattern: () => isURLPattern, + isXmlMimeType: () => isXmlMimeType, + locatorCustomDescription: () => locatorCustomDescription, + locatorOrSelectorAsSelector: () => locatorOrSelectorAsSelector, + longestCommonSubstring: () => longestCommonSubstring, + methodMetainfo: () => methodMetainfo, + monotonicTime: () => monotonicTime, + msToString: () => msToString, + nextActionByStartTime: () => nextActionByStartTime, + noColors: () => noColors, + normalizeEscapedRegexQuotes: () => normalizeEscapedRegexQuotes, + normalizeWhiteSpace: () => normalizeWhiteSpace, + padImageToSize: () => padImageToSize, + parseAriaSnapshot: () => parseAriaSnapshot, + parseAriaSnapshotUnsafe: () => parseAriaSnapshotUnsafe, + parseAttributeSelector: () => parseAttributeSelector, + parseCSS: () => parseCSS, + parseClientSideCallMetadata: () => parseClientSideCallMetadata, + parseErrorStack: () => parseErrorStack, + parseRegex: () => parseRegex, + parseSelector: () => parseSelector, + parseStackFrame: () => parseStackFrame, + pollAgainstDeadline: () => pollAgainstDeadline, + previousActionByEndTime: () => previousActionByEndTime, + quoteCSSAttributeValue: () => quoteCSSAttributeValue, + raceAgainstDeadline: () => raceAgainstDeadline, + renderTitleForCall: () => renderTitleForCall, + resolveGlobToRegexPattern: () => resolveGlobToRegexPattern, + rewriteErrorMessage: () => rewriteErrorMessage, + scaleImageToSize: () => scaleImageToSize, + serializeClientSideCallMetadata: () => serializeClientSideCallMetadata, + serializeExpectedTextValues: () => serializeExpectedTextValues, + serializeSelector: () => serializeSelector, + serializeURLMatch: () => serializeURLMatch, + serializeURLPattern: () => serializeURLPattern, + setTimeOrigin: () => setTimeOrigin, + signalToPromise: () => signalToPromise, + splitErrorMessage: () => splitErrorMessage, + splitSelectorByFrame: () => splitSelectorByFrame, + stats: () => stats, + stringifySelector: () => stringifySelector, + stringifyStackFrames: () => stringifyStackFrames, + stripAnsiEscapes: () => stripAnsiEscapes, + textValue: () => textValue, + timeOrigin: () => timeOrigin, + toSnakeCase: () => toSnakeCase, + toTitleCase: () => toTitleCase, + tomlArray: () => tomlArray, + tomlBasicString: () => tomlBasicString, + tomlMultilineBasicString: () => tomlMultilineBasicString, + trimString: () => trimString, + trimStringWithEllipsis: () => trimStringWithEllipsis, + unsafeLocatorOrSelectorAsSelector: () => unsafeLocatorOrSelectorAsSelector, + urlMatches: () => urlMatches, + urlMatchesEqual: () => urlMatchesEqual, + validate: () => validate, + visitAllSelectorParts: () => visitAllSelectorParts, + webColors: () => webColors, + yamlEscapeKeyIfNeeded: () => yamlEscapeKeyIfNeeded, + yamlEscapeValueIfNeeded: () => yamlEscapeValueIfNeeded +}); +var init_isomorphic = __esm({ + "packages/isomorphic/index.ts"() { + "use strict"; + init_ariaSnapshot(); + init_expectUtils(); + init_assert(); + init_base64(); + init_colors(); + init_headers(); + init_imageUtils(); + init_jsonSchema(); + init_locatorGenerators(); + init_manualPromise(); + init_mimeType(); + init_multimap(); + init_protocolFormatter(); + init_protocolMetainfo(); + init_rtti(); + init_semaphore(); + init_stackTrace(); + init_stringUtils(); + init_formatUtils(); + init_time(); + init_timeoutRunner(); + init_snapshotServer(); + init_urlMatch(); + init_cssParser(); + init_locatorParser(); + init_selectorParser(); + init_snapshotStorage(); + init_traceLoader(); + init_traceModel(); + init_traceUtils(); + init_yaml(); + } +}); + +// packages/utils/ascii.ts +function wrapInASCIIBox(text2, padding = 0) { + const lines = text2.split("\n"); + const maxLength = Math.max(...lines.map((line) => line.length)); + return [ + "\u2554" + "\u2550".repeat(maxLength + padding * 2) + "\u2557", + ...lines.map((line) => "\u2551" + " ".repeat(padding) + line + " ".repeat(maxLength - line.length + padding) + "\u2551"), + "\u255A" + "\u2550".repeat(maxLength + padding * 2) + "\u255D" + ].join("\n"); +} +function jsonStringifyForceASCII(object) { + return JSON.stringify(object).replace( + /[\u007f-\uffff]/g, + (c) => "\\u" + ("0000" + c.charCodeAt(0).toString(16)).slice(-4) + ); +} +var init_ascii = __esm({ + "packages/utils/ascii.ts"() { + "use strict"; + } +}); + +// packages/utils/chromiumChannels.ts +function defaultUserDataDirForChannel(channel) { + return channelToDefaultUserDataDir.get(channel)?.[process.platform]; +} +function isChromiumChannelName(channel) { + return channelToDefaultUserDataDir.has(channel); +} +var import_os, import_path, channelToDefaultUserDataDir; +var init_chromiumChannels = __esm({ + "packages/utils/chromiumChannels.ts"() { + "use strict"; + import_os = __toESM(require("os")); + import_path = __toESM(require("path")); + channelToDefaultUserDataDir = /* @__PURE__ */ new Map([ + ["chrome", { + "linux": import_path.default.join(import_os.default.homedir(), ".config", "google-chrome"), + "darwin": import_path.default.join(import_os.default.homedir(), "Library", "Application Support", "Google", "Chrome"), + "win32": import_path.default.join(process.env.LOCALAPPDATA || import_path.default.join(import_os.default.homedir(), "AppData", "Local"), "Google", "Chrome", "User Data") + }], + ["chrome-beta", { + "linux": import_path.default.join(import_os.default.homedir(), ".config", "google-chrome-beta"), + "darwin": import_path.default.join(import_os.default.homedir(), "Library", "Application Support", "Google", "Chrome Beta"), + "win32": import_path.default.join(process.env.LOCALAPPDATA || import_path.default.join(import_os.default.homedir(), "AppData", "Local"), "Google", "Chrome Beta", "User Data") + }], + ["chrome-dev", { + "linux": import_path.default.join(import_os.default.homedir(), ".config", "google-chrome-unstable"), + "darwin": import_path.default.join(import_os.default.homedir(), "Library", "Application Support", "Google", "Chrome Dev"), + "win32": import_path.default.join(process.env.LOCALAPPDATA || import_path.default.join(import_os.default.homedir(), "AppData", "Local"), "Google", "Chrome Dev", "User Data") + }], + ["chrome-canary", { + "linux": import_path.default.join(import_os.default.homedir(), ".config", "google-chrome-canary"), + "darwin": import_path.default.join(import_os.default.homedir(), "Library", "Application Support", "Google", "Chrome Canary"), + "win32": import_path.default.join(process.env.LOCALAPPDATA || import_path.default.join(import_os.default.homedir(), "AppData", "Local"), "Google", "Chrome SxS", "User Data") + }], + ["msedge", { + "linux": import_path.default.join(import_os.default.homedir(), ".config", "microsoft-edge"), + "darwin": import_path.default.join(import_os.default.homedir(), "Library", "Application Support", "Microsoft Edge"), + "win32": import_path.default.join(process.env.LOCALAPPDATA || import_path.default.join(import_os.default.homedir(), "AppData", "Local"), "Microsoft", "Edge", "User Data") + }], + ["msedge-beta", { + "linux": import_path.default.join(import_os.default.homedir(), ".config", "microsoft-edge-beta"), + "darwin": import_path.default.join(import_os.default.homedir(), "Library", "Application Support", "Microsoft Edge Beta"), + "win32": import_path.default.join(process.env.LOCALAPPDATA || import_path.default.join(import_os.default.homedir(), "AppData", "Local"), "Microsoft", "Edge Beta", "User Data") + }], + ["msedge-dev", { + "linux": import_path.default.join(import_os.default.homedir(), ".config", "microsoft-edge-dev"), + "darwin": import_path.default.join(import_os.default.homedir(), "Library", "Application Support", "Microsoft Edge Dev"), + "win32": import_path.default.join(process.env.LOCALAPPDATA || import_path.default.join(import_os.default.homedir(), "AppData", "Local"), "Microsoft", "Edge Dev", "User Data") + }], + ["msedge-canary", { + "linux": import_path.default.join(import_os.default.homedir(), ".config", "microsoft-edge-canary"), + "darwin": import_path.default.join(import_os.default.homedir(), "Library", "Application Support", "Microsoft Edge Canary"), + "win32": import_path.default.join(process.env.LOCALAPPDATA || import_path.default.join(import_os.default.homedir(), "AppData", "Local"), "Microsoft", "Edge SxS", "User Data") + }] + ]); + } +}); + +// packages/utils/third_party/pixelmatch.js +var require_pixelmatch = __commonJS({ + "packages/utils/third_party/pixelmatch.js"(exports2, module2) { + "use strict"; + module2.exports = pixelmatch2; + var defaultOptions = { + threshold: 0.1, + // matching threshold (0 to 1); smaller is more sensitive + includeAA: false, + // whether to skip anti-aliasing detection + alpha: 0.1, + // opacity of original image in diff output + aaColor: [255, 255, 0], + // color of anti-aliased pixels in diff output + diffColor: [255, 0, 0], + // color of different pixels in diff output + diffColorAlt: null, + // whether to detect dark on light differences between img1 and img2 and set an alternative color to differentiate between the two + diffMask: false + // draw the diff over a transparent background (a mask) + }; + function pixelmatch2(img1, img2, output, width, height, options) { + if (!isPixelData(img1) || !isPixelData(img2) || output && !isPixelData(output)) + throw new Error("Image data: Uint8Array, Uint8ClampedArray or Buffer expected."); + if (img1.length !== img2.length || output && output.length !== img1.length) + throw new Error("Image sizes do not match."); + if (img1.length !== width * height * 4) throw new Error("Image data size does not match width/height."); + options = Object.assign({}, defaultOptions, options); + const len = width * height; + const a32 = new Uint32Array(img1.buffer, img1.byteOffset, len); + const b32 = new Uint32Array(img2.buffer, img2.byteOffset, len); + let identical = true; + for (let i = 0; i < len; i++) { + if (a32[i] !== b32[i]) { + identical = false; + break; + } + } + if (identical) { + if (output && !options.diffMask) { + for (let i = 0; i < len; i++) drawGrayPixel(img1, 4 * i, options.alpha, output); + } + return 0; + } + const maxDelta = 35215 * options.threshold * options.threshold; + let diff2 = 0; + for (let y = 0; y < height; y++) { + for (let x = 0; x < width; x++) { + const pos = (y * width + x) * 4; + const delta = colorDelta(img1, img2, pos, pos); + if (Math.abs(delta) > maxDelta) { + if (!options.includeAA && (antialiased(img1, x, y, width, height, img2) || antialiased(img2, x, y, width, height, img1))) { + if (output && !options.diffMask) drawPixel2(output, pos, ...options.aaColor); + } else { + if (output) { + drawPixel2(output, pos, ...delta < 0 && options.diffColorAlt || options.diffColor); + } + diff2++; + } + } else if (output) { + if (!options.diffMask) drawGrayPixel(img1, pos, options.alpha, output); + } + } + } + return diff2; + } + function isPixelData(arr) { + return ArrayBuffer.isView(arr) && arr.constructor.BYTES_PER_ELEMENT === 1; + } + function antialiased(img, x1, y1, width, height, img2) { + const x0 = Math.max(x1 - 1, 0); + const y0 = Math.max(y1 - 1, 0); + const x2 = Math.min(x1 + 1, width - 1); + const y2 = Math.min(y1 + 1, height - 1); + const pos = (y1 * width + x1) * 4; + let zeroes = x1 === x0 || x1 === x2 || y1 === y0 || y1 === y2 ? 1 : 0; + let min = 0; + let max = 0; + let minX, minY, maxX, maxY; + for (let x = x0; x <= x2; x++) { + for (let y = y0; y <= y2; y++) { + if (x === x1 && y === y1) continue; + const delta = colorDelta(img, img, pos, (y * width + x) * 4, true); + if (delta === 0) { + zeroes++; + if (zeroes > 2) return false; + } else if (delta < min) { + min = delta; + minX = x; + minY = y; + } else if (delta > max) { + max = delta; + maxX = x; + maxY = y; + } + } + } + if (min === 0 || max === 0) return false; + return hasManySiblings(img, minX, minY, width, height) && hasManySiblings(img2, minX, minY, width, height) || hasManySiblings(img, maxX, maxY, width, height) && hasManySiblings(img2, maxX, maxY, width, height); + } + function hasManySiblings(img, x1, y1, width, height) { + const x0 = Math.max(x1 - 1, 0); + const y0 = Math.max(y1 - 1, 0); + const x2 = Math.min(x1 + 1, width - 1); + const y2 = Math.min(y1 + 1, height - 1); + const pos = (y1 * width + x1) * 4; + let zeroes = x1 === x0 || x1 === x2 || y1 === y0 || y1 === y2 ? 1 : 0; + for (let x = x0; x <= x2; x++) { + for (let y = y0; y <= y2; y++) { + if (x === x1 && y === y1) continue; + const pos2 = (y * width + x) * 4; + if (img[pos] === img[pos2] && img[pos + 1] === img[pos2 + 1] && img[pos + 2] === img[pos2 + 2] && img[pos + 3] === img[pos2 + 3]) zeroes++; + if (zeroes > 2) return true; + } + } + return false; + } + function colorDelta(img1, img2, k, m, yOnly) { + let r1 = img1[k + 0]; + let g1 = img1[k + 1]; + let b1 = img1[k + 2]; + let a1 = img1[k + 3]; + let r2 = img2[m + 0]; + let g2 = img2[m + 1]; + let b2 = img2[m + 2]; + let a2 = img2[m + 3]; + if (a1 === a2 && r1 === r2 && g1 === g2 && b1 === b2) return 0; + if (a1 < 255) { + a1 /= 255; + r1 = blend(r1, a1); + g1 = blend(g1, a1); + b1 = blend(b1, a1); + } + if (a2 < 255) { + a2 /= 255; + r2 = blend(r2, a2); + g2 = blend(g2, a2); + b2 = blend(b2, a2); + } + const y1 = rgb2y(r1, g1, b1); + const y2 = rgb2y(r2, g2, b2); + const y = y1 - y2; + if (yOnly) return y; + const i = rgb2i(r1, g1, b1) - rgb2i(r2, g2, b2); + const q = rgb2q(r1, g1, b1) - rgb2q(r2, g2, b2); + const delta = 0.5053 * y * y + 0.299 * i * i + 0.1957 * q * q; + return y1 > y2 ? -delta : delta; + } + function rgb2y(r, g, b) { + return r * 0.29889531 + g * 0.58662247 + b * 0.11448223; + } + function rgb2i(r, g, b) { + return r * 0.59597799 - g * 0.2741761 - b * 0.32180189; + } + function rgb2q(r, g, b) { + return r * 0.21147017 - g * 0.52261711 + b * 0.31114694; + } + function blend(c, a) { + return 255 + (c - 255) * a; + } + function drawPixel2(output, pos, r, g, b) { + output[pos + 0] = r; + output[pos + 1] = g; + output[pos + 2] = b; + output[pos + 3] = 255; + } + function drawGrayPixel(img, i, alpha, output) { + const r = img[i + 0]; + const g = img[i + 1]; + const b = img[i + 2]; + const val = blend(rgb2y(r, g, b), alpha * img[i + 3] / 255); + drawPixel2(output, i, val, val, val); + } + } +}); + +// packages/utils/image_tools/colorUtils.ts +function blendWithWhite(c, a) { + return 255 + (c - 255) * a; +} +function rgb2gray(r, g, b) { + return 77 * r + 150 * g + 29 * b + 128 >> 8; +} +function colorDeltaE94(rgb1, rgb2) { + const [l1, a1, b1] = xyz2lab(srgb2xyz(rgb1)); + const [l2, a2, b2] = xyz2lab(srgb2xyz(rgb2)); + const deltaL = l1 - l2; + const deltaA = a1 - a2; + const deltaB = b1 - b2; + const c1 = Math.sqrt(a1 ** 2 + b1 ** 2); + const c2 = Math.sqrt(a2 ** 2 + b2 ** 2); + const deltaC = c1 - c2; + let deltaH = deltaA ** 2 + deltaB ** 2 - deltaC ** 2; + deltaH = deltaH < 0 ? 0 : Math.sqrt(deltaH); + const k1 = 0.045; + const k2 = 0.015; + const kL = 1; + const kC = 1; + const kH = 1; + const sC = 1 + k1 * c1; + const sH = 1 + k2 * c1; + const sL = 1; + return Math.sqrt((deltaL / sL / kL) ** 2 + (deltaC / sC / kC) ** 2 + (deltaH / sH / kH) ** 2); +} +function srgb2xyz(rgb) { + let r = rgb[0] / 255; + let g = rgb[1] / 255; + let b = rgb[2] / 255; + r = r > 0.04045 ? Math.pow((r + 0.055) / 1.055, 2.4) : r / 12.92; + g = g > 0.04045 ? Math.pow((g + 0.055) / 1.055, 2.4) : g / 12.92; + b = b > 0.04045 ? Math.pow((b + 0.055) / 1.055, 2.4) : b / 12.92; + return [ + r * 0.4124 + g * 0.3576 + b * 0.1805, + r * 0.2126 + g * 0.7152 + b * 0.0722, + r * 0.0193 + g * 0.1192 + b * 0.9505 + ]; +} +function xyz2lab(xyz) { + const x = xyz[0] / 0.950489; + const y = xyz[1]; + const z31 = xyz[2] / 1.08884; + const fx = x > sigma_pow3 ? x ** (1 / 3) : x / 3 / sigma_pow2 + 4 / 29; + const fy = y > sigma_pow3 ? y ** (1 / 3) : y / 3 / sigma_pow2 + 4 / 29; + const fz = z31 > sigma_pow3 ? z31 ** (1 / 3) : z31 / 3 / sigma_pow2 + 4 / 29; + const l = 116 * fy - 16; + const a = 500 * (fx - fy); + const b = 200 * (fy - fz); + return [l, a, b]; +} +var sigma_pow2, sigma_pow3; +var init_colorUtils = __esm({ + "packages/utils/image_tools/colorUtils.ts"() { + "use strict"; + sigma_pow2 = 6 * 6 / 29 / 29; + sigma_pow3 = 6 * 6 * 6 / 29 / 29 / 29; + } +}); + +// packages/utils/image_tools/imageChannel.ts +var ImageChannel; +var init_imageChannel = __esm({ + "packages/utils/image_tools/imageChannel.ts"() { + "use strict"; + init_colorUtils(); + ImageChannel = class _ImageChannel { + static intoRGB(width, height, data, options = {}) { + const { + paddingSize = 0, + paddingColorOdd = [255, 0, 255], + paddingColorEven = [0, 255, 0] + } = options; + const newWidth = width + 2 * paddingSize; + const newHeight = height + 2 * paddingSize; + const r = new Uint8Array(newWidth * newHeight); + const g = new Uint8Array(newWidth * newHeight); + const b = new Uint8Array(newWidth * newHeight); + for (let y = 0; y < newHeight; ++y) { + for (let x = 0; x < newWidth; ++x) { + const index = y * newWidth + x; + if (y >= paddingSize && y < newHeight - paddingSize && x >= paddingSize && x < newWidth - paddingSize) { + const offset = ((y - paddingSize) * width + (x - paddingSize)) * 4; + const alpha = data[offset + 3] === 255 ? 1 : data[offset + 3] / 255; + r[index] = blendWithWhite(data[offset], alpha); + g[index] = blendWithWhite(data[offset + 1], alpha); + b[index] = blendWithWhite(data[offset + 2], alpha); + } else { + const color = (y + x) % 2 === 0 ? paddingColorEven : paddingColorOdd; + r[index] = color[0]; + g[index] = color[1]; + b[index] = color[2]; + } + } + } + return [ + new _ImageChannel(newWidth, newHeight, r), + new _ImageChannel(newWidth, newHeight, g), + new _ImageChannel(newWidth, newHeight, b) + ]; + } + constructor(width, height, data) { + this.data = data; + this.width = width; + this.height = height; + } + get(x, y) { + return this.data[y * this.width + x]; + } + boundXY(x, y) { + return [ + Math.min(Math.max(x, 0), this.width - 1), + Math.min(Math.max(y, 0), this.height - 1) + ]; + } + }; + } +}); + +// packages/utils/image_tools/stats.ts +function ssim(stats2, x1, y1, x2, y2) { + const mean1 = stats2.meanC1(x1, y1, x2, y2); + const mean2 = stats2.meanC2(x1, y1, x2, y2); + const var1 = stats2.varianceC1(x1, y1, x2, y2); + const var2 = stats2.varianceC2(x1, y1, x2, y2); + const cov = stats2.covariance(x1, y1, x2, y2); + const c1 = (0.01 * DYNAMIC_RANGE) ** 2; + const c2 = (0.03 * DYNAMIC_RANGE) ** 2; + return (2 * mean1 * mean2 + c1) * (2 * cov + c2) / (mean1 ** 2 + mean2 ** 2 + c1) / (var1 + var2 + c2); +} +var DYNAMIC_RANGE, FastStats; +var init_stats = __esm({ + "packages/utils/image_tools/stats.ts"() { + "use strict"; + DYNAMIC_RANGE = 2 ** 8 - 1; + FastStats = class { + constructor(c1, c2) { + this.c1 = c1; + this.c2 = c2; + const { width, height } = c1; + this._partialSumC1 = new Array(width * height); + this._partialSumC2 = new Array(width * height); + this._partialSumSq1 = new Array(width * height); + this._partialSumSq2 = new Array(width * height); + this._partialSumMult = new Array(width * height); + const recalc = (mx, idx, initial, x, y) => { + mx[idx] = initial; + if (y > 0) + mx[idx] += mx[(y - 1) * width + x]; + if (x > 0) + mx[idx] += mx[y * width + x - 1]; + if (x > 0 && y > 0) + mx[idx] -= mx[(y - 1) * width + x - 1]; + }; + for (let y = 0; y < height; ++y) { + for (let x = 0; x < width; ++x) { + const idx = y * width + x; + recalc(this._partialSumC1, idx, this.c1.data[idx], x, y); + recalc(this._partialSumC2, idx, this.c2.data[idx], x, y); + recalc(this._partialSumSq1, idx, this.c1.data[idx] * this.c1.data[idx], x, y); + recalc(this._partialSumSq2, idx, this.c2.data[idx] * this.c2.data[idx], x, y); + recalc(this._partialSumMult, idx, this.c1.data[idx] * this.c2.data[idx], x, y); + } + } + } + _sum(partialSum, x1, y1, x2, y2) { + const width = this.c1.width; + let result2 = partialSum[y2 * width + x2]; + if (y1 > 0) + result2 -= partialSum[(y1 - 1) * width + x2]; + if (x1 > 0) + result2 -= partialSum[y2 * width + x1 - 1]; + if (x1 > 0 && y1 > 0) + result2 += partialSum[(y1 - 1) * width + x1 - 1]; + return result2; + } + meanC1(x1, y1, x2, y2) { + const N = (y2 - y1 + 1) * (x2 - x1 + 1); + return this._sum(this._partialSumC1, x1, y1, x2, y2) / N; + } + meanC2(x1, y1, x2, y2) { + const N = (y2 - y1 + 1) * (x2 - x1 + 1); + return this._sum(this._partialSumC2, x1, y1, x2, y2) / N; + } + varianceC1(x1, y1, x2, y2) { + const N = (y2 - y1 + 1) * (x2 - x1 + 1); + return (this._sum(this._partialSumSq1, x1, y1, x2, y2) - this._sum(this._partialSumC1, x1, y1, x2, y2) ** 2 / N) / N; + } + varianceC2(x1, y1, x2, y2) { + const N = (y2 - y1 + 1) * (x2 - x1 + 1); + return (this._sum(this._partialSumSq2, x1, y1, x2, y2) - this._sum(this._partialSumC2, x1, y1, x2, y2) ** 2 / N) / N; + } + covariance(x1, y1, x2, y2) { + const N = (y2 - y1 + 1) * (x2 - x1 + 1); + return (this._sum(this._partialSumMult, x1, y1, x2, y2) - this._sum(this._partialSumC1, x1, y1, x2, y2) * this._sum(this._partialSumC2, x1, y1, x2, y2) / N) / N; + } + }; + } +}); + +// packages/utils/image_tools/compare.ts +function drawPixel(width, data, x, y, r, g, b) { + const idx = (y * width + x) * 4; + data[idx + 0] = r; + data[idx + 1] = g; + data[idx + 2] = b; + data[idx + 3] = 255; +} +function compare(actual, expected, diff2, width, height, options = {}) { + const { + maxColorDeltaE94 = 1 + } = options; + const paddingSize = Math.max(VARIANCE_WINDOW_RADIUS, SSIM_WINDOW_RADIUS); + const paddingColorEven = [255, 0, 255]; + const paddingColorOdd = [0, 255, 0]; + const [r1, g1, b1] = ImageChannel.intoRGB(width, height, expected, { + paddingSize, + paddingColorEven, + paddingColorOdd + }); + const [r2, g2, b2] = ImageChannel.intoRGB(width, height, actual, { + paddingSize, + paddingColorEven, + paddingColorOdd + }); + const noop = (x, y) => { + }; + const drawRedPixel = diff2 ? (x, y) => drawPixel(width, diff2, x - paddingSize, y - paddingSize, 255, 0, 0) : noop; + const drawYellowPixel = diff2 ? (x, y) => drawPixel(width, diff2, x - paddingSize, y - paddingSize, 255, 255, 0) : noop; + const drawGrayPixel = diff2 ? (x, y) => { + const gray = rgb2gray(r1.get(x, y), g1.get(x, y), b1.get(x, y)); + const value2 = blendWithWhite(gray, 0.1); + drawPixel(width, diff2, x - paddingSize, y - paddingSize, value2, value2, value2); + } : noop; + let fastR; + let fastG; + let fastB; + let diffCount = 0; + for (let y = paddingSize; y < r1.height - paddingSize; ++y) { + for (let x = paddingSize; x < r1.width - paddingSize; ++x) { + if (r1.get(x, y) === r2.get(x, y) && g1.get(x, y) === g2.get(x, y) && b1.get(x, y) === b2.get(x, y)) { + drawGrayPixel(x, y); + continue; + } + const delta = colorDeltaE94( + [r1.get(x, y), g1.get(x, y), b1.get(x, y)], + [r2.get(x, y), g2.get(x, y), b2.get(x, y)] + ); + if (delta <= maxColorDeltaE94) { + drawGrayPixel(x, y); + continue; + } + if (!fastR || !fastG || !fastB) { + fastR = new FastStats(r1, r2); + fastG = new FastStats(g1, g2); + fastB = new FastStats(b1, b2); + } + const [varX1, varY1] = r1.boundXY(x - VARIANCE_WINDOW_RADIUS, y - VARIANCE_WINDOW_RADIUS); + const [varX2, varY2] = r1.boundXY(x + VARIANCE_WINDOW_RADIUS, y + VARIANCE_WINDOW_RADIUS); + const var1 = fastR.varianceC1(varX1, varY1, varX2, varY2) + fastG.varianceC1(varX1, varY1, varX2, varY2) + fastB.varianceC1(varX1, varY1, varX2, varY2); + const var2 = fastR.varianceC2(varX1, varY1, varX2, varY2) + fastG.varianceC2(varX1, varY1, varX2, varY2) + fastB.varianceC2(varX1, varY1, varX2, varY2); + if (var1 === 0 || var2 === 0) { + drawRedPixel(x, y); + ++diffCount; + continue; + } + const [ssimX1, ssimY1] = r1.boundXY(x - SSIM_WINDOW_RADIUS, y - SSIM_WINDOW_RADIUS); + const [ssimX2, ssimY2] = r1.boundXY(x + SSIM_WINDOW_RADIUS, y + SSIM_WINDOW_RADIUS); + const ssimRGB = (ssim(fastR, ssimX1, ssimY1, ssimX2, ssimY2) + ssim(fastG, ssimX1, ssimY1, ssimX2, ssimY2) + ssim(fastB, ssimX1, ssimY1, ssimX2, ssimY2)) / 3; + const isAntialiased = ssimRGB >= 0.99; + if (isAntialiased) { + drawYellowPixel(x, y); + } else { + drawRedPixel(x, y); + ++diffCount; + } + } + } + return diffCount; +} +var SSIM_WINDOW_RADIUS, VARIANCE_WINDOW_RADIUS; +var init_compare = __esm({ + "packages/utils/image_tools/compare.ts"() { + "use strict"; + init_colorUtils(); + init_imageChannel(); + init_stats(); + SSIM_WINDOW_RADIUS = 15; + VARIANCE_WINDOW_RADIUS = 1; + } +}); + +// packages/utils/comparators.ts +function getComparator(mimeType) { + if (mimeType === "image/png") + return compareImages.bind(null, "image/png"); + if (mimeType === "image/jpeg") + return compareImages.bind(null, "image/jpeg"); + if (mimeType === "text/plain") + return compareText; + return compareBuffersOrStrings; +} +function compareBuffersOrStrings(actualBuffer, expectedBuffer) { + if (typeof actualBuffer === "string") + return compareText(actualBuffer, expectedBuffer); + if (!actualBuffer || !(actualBuffer instanceof Buffer)) + return { errorMessage: "Actual result should be a Buffer or a string." }; + if (Buffer.compare(actualBuffer, expectedBuffer)) + return { errorMessage: "Buffers differ" }; + return null; +} +function compareImages(mimeType, actualBuffer, expectedBuffer, options = {}) { + if (!actualBuffer || !(actualBuffer instanceof Buffer)) + return { errorMessage: "Actual result should be a Buffer." }; + validateBuffer(expectedBuffer, mimeType); + let actual = mimeType === "image/png" ? PNG.sync.read(actualBuffer) : jpegjs.decode(actualBuffer, { maxMemoryUsageInMB: JPEG_JS_MAX_BUFFER_SIZE_IN_MB }); + let expected = mimeType === "image/png" ? PNG.sync.read(expectedBuffer) : jpegjs.decode(expectedBuffer, { maxMemoryUsageInMB: JPEG_JS_MAX_BUFFER_SIZE_IN_MB }); + const size = { width: Math.max(expected.width, actual.width), height: Math.max(expected.height, actual.height) }; + let sizesMismatchError = ""; + if (expected.width !== actual.width || expected.height !== actual.height) { + sizesMismatchError = `Expected an image ${expected.width}px by ${expected.height}px, received ${actual.width}px by ${actual.height}px. `; + actual = padImageToSize(actual, size); + expected = padImageToSize(expected, size); + } + const diff2 = new PNG({ width: size.width, height: size.height }); + let count; + if (options.comparator === "ssim-cie94") { + count = compare(expected.data, actual.data, diff2.data, size.width, size.height, { + // All ΔE* formulae are originally designed to have the difference of 1.0 stand for a "just noticeable difference" (JND). + // See https://en.wikipedia.org/wiki/Color_difference#CIELAB_%CE%94E* + maxColorDeltaE94: 1 + }); + } else if ((options.comparator ?? "pixelmatch") === "pixelmatch") { + count = (0, import_pixelmatch.default)(expected.data, actual.data, diff2.data, size.width, size.height, { + threshold: options.threshold ?? 0.2 + }); + } else { + throw new Error(`Configuration specifies unknown comparator "${options.comparator}"`); + } + const maxDiffPixels1 = options.maxDiffPixels; + const maxDiffPixels2 = options.maxDiffPixelRatio !== void 0 ? expected.width * expected.height * options.maxDiffPixelRatio : void 0; + let maxDiffPixels; + if (maxDiffPixels1 !== void 0 && maxDiffPixels2 !== void 0) + maxDiffPixels = Math.min(maxDiffPixels1, maxDiffPixels2); + else + maxDiffPixels = maxDiffPixels1 ?? maxDiffPixels2 ?? 0; + const ratio = Math.ceil(count / (expected.width * expected.height) * 100) / 100; + const pixelsMismatchError = count > maxDiffPixels ? `${count} pixels (ratio ${ratio.toFixed(2)} of all image pixels) are different.` : ""; + if (pixelsMismatchError || sizesMismatchError) + return { errorMessage: sizesMismatchError + pixelsMismatchError, diff: PNG.sync.write(diff2) }; + return null; +} +function validateBuffer(buffer, mimeType) { + if (mimeType === "image/png") { + const pngMagicNumber = [137, 80, 78, 71, 13, 10, 26, 10]; + if (buffer.length < pngMagicNumber.length || !pngMagicNumber.every((byte, index) => buffer[index] === byte)) + throw new Error("Could not decode expected image as PNG."); + } else if (mimeType === "image/jpeg") { + const jpegMagicNumber = [255, 216]; + if (buffer.length < jpegMagicNumber.length || !jpegMagicNumber.every((byte, index) => buffer[index] === byte)) + throw new Error("Could not decode expected image as JPEG."); + } +} +function compareText(actual, expectedBuffer) { + if (typeof actual !== "string") + return { errorMessage: "Actual result should be a string" }; + let expected = expectedBuffer.toString("utf-8"); + if (expected === actual) + return null; + if (!actual.endsWith("\n")) + actual += "\n"; + if (!expected.endsWith("\n")) + expected += "\n"; + const lines = diff.createPatch("file", expected, actual, void 0, void 0, { context: 5 }).split("\n"); + const coloredLines = lines.slice(4).map((line) => { + if (line.startsWith("-")) + return colors.green(line); + if (line.startsWith("+")) + return colors.red(line); + if (line.startsWith("@@")) + return colors.dim(line); + return line; + }); + const errorMessage = coloredLines.join("\n"); + return { errorMessage }; +} +var import_pixelmatch, jpegjs, colors, diff, PNG, JPEG_JS_MAX_BUFFER_SIZE_IN_MB; +var init_comparators = __esm({ + "packages/utils/comparators.ts"() { + "use strict"; + init_imageUtils(); + import_pixelmatch = __toESM(require_pixelmatch()); + init_compare(); + jpegjs = require("./utilsBundle").jpegjs; + colors = require("./utilsBundle").colors; + diff = require("./utilsBundle").diff; + ({ PNG } = require("./utilsBundle")); + JPEG_JS_MAX_BUFFER_SIZE_IN_MB = 5 * 1024; + } +}); + +// packages/utils/crypto.ts +function createGuid() { + return import_crypto.default.randomBytes(16).toString("hex"); +} +function calculateSha1(buffer) { + const hash = import_crypto.default.createHash("sha1"); + hash.update(buffer); + return hash.digest("hex"); +} +function encodeBase128(value2) { + const bytes = []; + do { + let byte = value2 & 127; + value2 >>>= 7; + if (bytes.length > 0) + byte |= 128; + bytes.push(byte); + } while (value2 > 0); + return Buffer.from(bytes.reverse()); +} +function generateSelfSignedCertificate() { + const { privateKey, publicKey } = import_crypto.default.generateKeyPairSync("rsa", { modulusLength: 2048 }); + const publicKeyDer = publicKey.export({ type: "pkcs1", format: "der" }); + const oneYearInMilliseconds = 365 * 24 * 60 * 60 * 1e3; + const notBefore = new Date((/* @__PURE__ */ new Date()).getTime() - oneYearInMilliseconds); + const notAfter = new Date((/* @__PURE__ */ new Date()).getTime() + oneYearInMilliseconds); + const tbsCertificate = DER.encodeSequence([ + DER.encodeExplicitContextDependent(0, DER.encodeInteger(1)), + // version + DER.encodeInteger(1), + // serialNumber + DER.encodeSequence([ + DER.encodeObjectIdentifier("1.2.840.113549.1.1.11"), + // sha256WithRSAEncryption PKCS #1 + DER.encodeNull() + ]), + // signature + DER.encodeSequence([ + DER.encodeSet([ + DER.encodeSequence([ + DER.encodeObjectIdentifier("2.5.4.3"), + // commonName X.520 DN component + DER.encodePrintableString("localhost") + ]) + ]), + DER.encodeSet([ + DER.encodeSequence([ + DER.encodeObjectIdentifier("2.5.4.10"), + // organizationName X.520 DN component + DER.encodePrintableString("Playwright Client Certificate Support") + ]) + ]) + ]), + // issuer + DER.encodeSequence([ + DER.encodeDate(notBefore), + // notBefore + DER.encodeDate(notAfter) + // notAfter + ]), + // validity + DER.encodeSequence([ + DER.encodeSet([ + DER.encodeSequence([ + DER.encodeObjectIdentifier("2.5.4.3"), + // commonName X.520 DN component + DER.encodePrintableString("localhost") + ]) + ]), + DER.encodeSet([ + DER.encodeSequence([ + DER.encodeObjectIdentifier("2.5.4.10"), + // organizationName X.520 DN component + DER.encodePrintableString("Playwright Client Certificate Support") + ]) + ]) + ]), + // subject + DER.encodeSequence([ + DER.encodeSequence([ + DER.encodeObjectIdentifier("1.2.840.113549.1.1.1"), + // rsaEncryption PKCS #1 + DER.encodeNull() + ]), + DER.encodeBitString(publicKeyDer) + ]) + // SubjectPublicKeyInfo + ]); + const signature = import_crypto.default.sign("sha256", tbsCertificate, privateKey); + const certificate = DER.encodeSequence([ + tbsCertificate, + DER.encodeSequence([ + DER.encodeObjectIdentifier("1.2.840.113549.1.1.11"), + // sha256WithRSAEncryption PKCS #1 + DER.encodeNull() + ]), + DER.encodeBitString(signature) + ]); + const certPem = [ + "-----BEGIN CERTIFICATE-----", + // Split the base64 string into lines of 64 characters + certificate.toString("base64").match(/.{1,64}/g).join("\n"), + "-----END CERTIFICATE-----" + ].join("\n"); + return { + cert: certPem, + key: privateKey.export({ type: "pkcs1", format: "pem" }) + }; +} +var import_crypto, DER; +var init_crypto = __esm({ + "packages/utils/crypto.ts"() { + "use strict"; + import_crypto = __toESM(require("crypto")); + init_assert(); + DER = class { + static encodeSequence(data) { + return this._encode(48, Buffer.concat(data)); + } + static encodeInteger(data) { + assert(data >= -128 && data <= 127); + return this._encode(2, Buffer.from([data])); + } + static encodeObjectIdentifier(oid) { + const parts = oid.split(".").map((v) => Number(v)); + const output = [encodeBase128(40 * parts[0] + parts[1])]; + for (let i = 2; i < parts.length; i++) + output.push(encodeBase128(parts[i])); + return this._encode(6, Buffer.concat(output)); + } + static encodeNull() { + return Buffer.from([5, 0]); + } + static encodeSet(data) { + assert(data.length === 1, "Only one item in the set is supported. We'd need to sort the data to support more."); + return this._encode(49, Buffer.concat(data)); + } + static encodeExplicitContextDependent(tag, data) { + return this._encode(160 + tag, data); + } + static encodePrintableString(data) { + return this._encode(19, Buffer.from(data)); + } + static encodeBitString(data) { + const unusedBits = 0; + const content = Buffer.concat([Buffer.from([unusedBits]), data]); + return this._encode(3, content); + } + static encodeDate(date) { + const year = date.getUTCFullYear(); + const isGeneralizedTime = year >= 2050; + const parts = [ + isGeneralizedTime ? year.toString() : year.toString().slice(-2), + (date.getUTCMonth() + 1).toString().padStart(2, "0"), + date.getUTCDate().toString().padStart(2, "0"), + date.getUTCHours().toString().padStart(2, "0"), + date.getUTCMinutes().toString().padStart(2, "0"), + date.getUTCSeconds().toString().padStart(2, "0") + ]; + const encodedDate = parts.join("") + "Z"; + const tag = isGeneralizedTime ? 24 : 23; + return this._encode(tag, Buffer.from(encodedDate)); + } + static _encode(tag, data) { + const lengthBytes = this._encodeLength(data.length); + return Buffer.concat([Buffer.from([tag]), lengthBytes, data]); + } + static _encodeLength(length) { + if (length < 128) { + return Buffer.from([length]); + } else { + const lengthBytes = []; + while (length > 0) { + lengthBytes.unshift(length & 255); + length >>= 8; + } + return Buffer.from([128 | lengthBytes.length, ...lengthBytes]); + } + } + }; + } +}); + +// packages/utils/env.ts +function getFromENV(name) { + let value2 = process.env[name]; + value2 = value2 === void 0 ? process.env[`npm_config_${name.toLowerCase()}`] : value2; + value2 = value2 === void 0 ? process.env[`npm_package_config_${name.toLowerCase()}`] : value2; + return value2; +} +function getAsBooleanFromENV(name, defaultValue) { + const value2 = getFromENV(name); + if (value2 === "false" || value2 === "0") + return false; + if (value2) + return true; + return !!defaultValue; +} +function getPackageManager() { + const env = process.env.npm_config_user_agent || ""; + if (env.includes("yarn")) + return "yarn"; + if (env.includes("pnpm")) + return "pnpm"; + return "npm"; +} +function getPackageManagerExecCommand() { + const packageManager = getPackageManager(); + if (packageManager === "yarn") + return "yarn"; + if (packageManager === "pnpm") + return "pnpm exec"; + return "npx"; +} +function isLikelyNpxGlobal() { + return process.argv.length >= 2 && process.argv[1].includes("_npx"); +} +function setPlaywrightTestProcessEnv() { + return process.env["PLAYWRIGHT_TEST"] = "1"; +} +function guessClientName() { + if (process.env.CLAUDECODE) + return "Claude Code"; + if (process.env.COPILOT_CLI) + return "GitHub Copilot"; + return "playwright-cli"; +} +function isCodingAgent() { + return !!process.env.CLAUDECODE || !!process.env.COPILOT_CLI; +} +var init_env = __esm({ + "packages/utils/env.ts"() { + "use strict"; + } +}); + +// packages/utils/debug.ts +function debugMode() { + if (_debugMode === "console") + return "console"; + if (_debugMode === "0" || _debugMode === "false") + return ""; + return _debugMode ? "inspector" : ""; +} +function isUnderTest() { + return _isUnderTest; +} +var _debugMode, _isUnderTest; +var init_debug = __esm({ + "packages/utils/debug.ts"() { + "use strict"; + init_env(); + _debugMode = getFromENV("PWDEBUG") || ""; + _isUnderTest = getAsBooleanFromENV("PWTEST_UNDER_TEST"); + } +}); + +// packages/utils/debugLogger.ts +var import_fs, debug, debugLoggerColorMap, DebugLogger, debugLogger, kLogCount, RecentLogsCollector; +var init_debugLogger = __esm({ + "packages/utils/debugLogger.ts"() { + "use strict"; + import_fs = __toESM(require("fs")); + debug = require("./utilsBundle").debug; + debugLoggerColorMap = { + "api": 45, + // cyan + "protocol": 34, + // green + "install": 34, + // green + "download": 34, + // green + "browser": 0, + // reset + "socks": 92, + // purple + "client-certificates": 92, + // purple + "error": 160, + // red, + "channel": 33, + // blue + "server": 45, + // cyan + "server:channel": 34, + // green + "server:metadata": 33, + // blue, + "recorder": 45 + // cyan + }; + DebugLogger = class { + constructor() { + this._debuggers = /* @__PURE__ */ new Map(); + if (process.env.DEBUG_FILE) { + const ansiRegex2 = new RegExp([ + "[\\u001B\\u009B][[\\]()#;?]*(?:(?:(?:[a-zA-Z\\d]*(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]*)*)?\\u0007)", + "(?:(?:\\d{1,4}(?:;\\d{0,4})*)?[\\dA-PR-TZcf-ntqry=><~]))" + ].join("|"), "g"); + const stream3 = import_fs.default.createWriteStream(process.env.DEBUG_FILE); + debug.log = (data) => { + stream3.write(data.replace(ansiRegex2, "")); + stream3.write("\n"); + }; + } + } + log(name, message) { + let cachedDebugger = this._debuggers.get(name); + if (!cachedDebugger) { + cachedDebugger = debug(`pw:${name}`); + this._debuggers.set(name, cachedDebugger); + cachedDebugger.color = debugLoggerColorMap[name] || 0; + } + cachedDebugger(message); + } + isEnabled(name) { + return debug.enabled(`pw:${name}`); + } + }; + debugLogger = new DebugLogger(); + kLogCount = 150; + RecentLogsCollector = class { + constructor() { + this._logs = []; + this._listeners = []; + } + log(message) { + this._logs.push(message); + if (this._logs.length === kLogCount * 2) + this._logs.splice(0, kLogCount); + for (const listener of this._listeners) + listener(message); + } + recentLogs() { + if (this._logs.length > kLogCount) + return this._logs.slice(-kLogCount); + return this._logs; + } + onMessage(listener) { + for (const message of this._logs) + listener(message); + this._listeners.push(listener); + } + }; + } +}); + +// packages/utils/eventsHelper.ts +var EventsHelper, eventsHelper; +var init_eventsHelper = __esm({ + "packages/utils/eventsHelper.ts"() { + "use strict"; + EventsHelper = class { + static addEventListener(emitter, eventName, handler) { + emitter.on(eventName, handler); + return { emitter, eventName, handler, dispose: async () => { + emitter.removeListener(eventName, handler); + } }; + } + static removeEventListeners(listeners) { + for (const listener of listeners) + listener.emitter.removeListener(listener.eventName, listener.handler); + listeners.splice(0, listeners.length); + } + }; + eventsHelper = EventsHelper; + } +}); + +// packages/utils/fileUtils.ts +async function mkdirIfNeeded(filePath) { + await import_fs2.default.promises.mkdir(import_path2.default.dirname(filePath), { recursive: true }).catch(() => { + }); +} +async function removeFolders(dirs) { + return await Promise.all(dirs.map( + (dir) => import_fs2.default.promises.rm(dir, { recursive: true, force: true, maxRetries: 10 }).catch((e) => e) + )); +} +function canAccessFile(file) { + if (!file) + return false; + try { + import_fs2.default.accessSync(file); + return true; + } catch (e) { + return false; + } +} +function isWritable(file) { + try { + import_fs2.default.accessSync(file, import_fs2.default.constants.W_OK); + return true; + } catch { + return false; + } +} +function isSystemDirectory(dir) { + const resolved = import_path2.default.resolve(dir); + if (process.platform === "win32") { + const systemRoot = import_path2.default.resolve(process.env.SystemRoot || "C:\\Windows"); + return isPathInside(systemRoot.toLowerCase(), resolved.toLowerCase()); + } + return resolved === "/"; +} +async function copyFileAndMakeWritable(from, to) { + await import_fs2.default.promises.copyFile(from, to); + await import_fs2.default.promises.chmod(to, 436); +} +function addSuffixToFilePath(filePath, suffix) { + const ext = import_path2.default.extname(filePath); + const base = filePath.substring(0, filePath.length - ext.length); + return base + suffix + ext; +} +function sanitizeForFilePath(s) { + return s.replace(/[\x00-\x2C\x2E-\x2F\x3A-\x40\x5B-\x60\x7B-\x7F]+/g, "-"); +} +function trimLongString(s, length = 100) { + if (s.length <= length) + return s; + const hash = calculateSha1(s); + const middle = `-${hash.substring(0, 5)}-`; + const start3 = Math.floor((length - middle.length) / 2); + const end = length - middle.length - start3; + return s.substring(0, start3) + middle + s.slice(-end); +} +function isPathInside(root, candidate) { + const resolvedRoot = import_path2.default.resolve(root); + const resolvedCandidate = import_path2.default.resolve(candidate); + if (resolvedCandidate === resolvedRoot) + return true; + return resolvedCandidate.startsWith(resolvedRoot + import_path2.default.sep); +} +function resolveWithinRoot(root, fileName) { + if (import_path2.default.isAbsolute(fileName)) + return null; + const resolvedFile = import_path2.default.resolve(root, fileName); + return isPathInside(root, resolvedFile) ? resolvedFile : null; +} +function throwingResolveWithinRoot(root, fileName) { + const resolved = resolveWithinRoot(root, fileName); + if (!resolved) + throw new Error(`Path '${fileName}' escapes root directory`); + return resolved; +} +function toPosixPath(aPath) { + return aPath.split(import_path2.default.sep).join(import_path2.default.posix.sep); +} +function makeSocketPath(domain, name) { + const userNameHash = calculateSha1(process.env.USERNAME || process.env.USER || "default").slice(0, 8); + if (process.platform === "win32") { + const socketsDir = process.env.PWTEST_SOCKETS_DIR; + const suffix2 = socketsDir ? `-${calculateSha1(socketsDir).slice(0, 8)}` : ""; + return `\\\\.\\pipe\\pw-${userNameHash}-${domain}-${name}${suffix2}`; + } + const baseDir = process.env.PWTEST_SOCKETS_DIR || import_path2.default.join(import_os2.default.tmpdir(), `pw-${userNameHash}`); + const dir = import_path2.default.join(baseDir, domain); + const suffix = ".sock"; + const maxNameLength = UNIX_SOCKET_PATH_MAX - dir.length - import_path2.default.sep.length - suffix.length; + if (maxNameLength < 1) + throw new Error(`Socket directory path is too long (${dir.length} chars); set PWTEST_SOCKETS_DIR to a shorter location.`); + const fsFriendlyName = trimLongString(sanitizeForFilePath(name), maxNameLength); + const result2 = import_path2.default.join(dir, `${fsFriendlyName}${suffix}`); + import_fs2.default.mkdirSync(dir, { recursive: true }); + return result2; +} +var import_fs2, import_os2, import_path2, existsAsync, UNIX_SOCKET_PATH_MAX; +var init_fileUtils = __esm({ + "packages/utils/fileUtils.ts"() { + "use strict"; + import_fs2 = __toESM(require("fs")); + import_os2 = __toESM(require("os")); + import_path2 = __toESM(require("path")); + init_crypto(); + existsAsync = (path59) => new Promise((resolve) => import_fs2.default.stat(path59, (err) => resolve(!err))); + UNIX_SOCKET_PATH_MAX = 103; + } +}); + +// packages/utils/linuxUtils.ts +function getLinuxDistributionInfoSync() { + if (process.platform !== "linux") + return void 0; + if (!osRelease && !didFailToReadOSRelease) { + try { + const osReleaseText = import_fs3.default.readFileSync("/etc/os-release", "utf8"); + const fields = parseOSReleaseText(osReleaseText); + osRelease = { + id: fields.get("id") ?? "", + version: fields.get("version_id") ?? "" + }; + } catch (e) { + didFailToReadOSRelease = true; + } + } + return osRelease; +} +function parseOSReleaseText(osReleaseText) { + const fields = /* @__PURE__ */ new Map(); + for (const line of osReleaseText.split("\n")) { + const tokens = line.split("="); + const name = tokens.shift(); + let value2 = tokens.join("=").trim(); + if (value2.startsWith('"') && value2.endsWith('"')) + value2 = value2.substring(1, value2.length - 1); + if (!name) + continue; + fields.set(name.toLowerCase(), value2); + } + return fields; +} +var import_fs3, didFailToReadOSRelease, osRelease; +var init_linuxUtils = __esm({ + "packages/utils/linuxUtils.ts"() { + "use strict"; + import_fs3 = __toESM(require("fs")); + didFailToReadOSRelease = false; + } +}); + +// packages/utils/hostPlatform.ts +function calculatePlatform() { + if (process.env.PLAYWRIGHT_HOST_PLATFORM_OVERRIDE) { + return { + hostPlatform: process.env.PLAYWRIGHT_HOST_PLATFORM_OVERRIDE, + isOfficiallySupportedPlatform: false + }; + } + const platform = import_os3.default.platform(); + if (platform === "darwin") { + const ver = import_os3.default.release().split(".").map((a) => parseInt(a, 10)); + let macVersion = ""; + if (ver[0] < 18) { + macVersion = "mac10.13"; + } else if (ver[0] === 18) { + macVersion = "mac10.14"; + } else if (ver[0] === 19) { + macVersion = "mac10.15"; + } else if (ver[0] < 25) { + macVersion = "mac" + (ver[0] - 9); + if (import_os3.default.cpus().some((cpu) => cpu.model.includes("Apple"))) + macVersion += "-arm64"; + } else { + const LAST_STABLE_MACOS_MAJOR_VERSION = 26; + macVersion = "mac" + Math.min(ver[0] + 1, LAST_STABLE_MACOS_MAJOR_VERSION); + if (import_os3.default.cpus().some((cpu) => cpu.model.includes("Apple"))) + macVersion += "-arm64"; + } + return { hostPlatform: macVersion, isOfficiallySupportedPlatform: true }; + } + if (platform === "linux") { + if (!["x64", "arm64"].includes(import_os3.default.arch())) + return { hostPlatform: "", isOfficiallySupportedPlatform: false }; + const archSuffix = "-" + import_os3.default.arch(); + const distroInfo = getLinuxDistributionInfoSync(); + if (distroInfo?.id === "ubuntu" || distroInfo?.id === "pop" || distroInfo?.id === "neon" || distroInfo?.id === "tuxedo") { + const isUbuntu = distroInfo?.id === "ubuntu"; + const version3 = distroInfo?.version; + const major2 = parseInt(distroInfo.version, 10); + if (major2 < 20) + return { hostPlatform: "ubuntu18.04" + archSuffix, isOfficiallySupportedPlatform: false }; + if (major2 < 22) + return { hostPlatform: "ubuntu20.04" + archSuffix, isOfficiallySupportedPlatform: isUbuntu && version3 === "20.04" }; + if (major2 < 24) + return { hostPlatform: "ubuntu22.04" + archSuffix, isOfficiallySupportedPlatform: isUbuntu && version3 === "22.04" }; + if (major2 < 26) + return { hostPlatform: "ubuntu24.04" + archSuffix, isOfficiallySupportedPlatform: isUbuntu && version3 === "24.04" }; + if (major2 < 28) + return { hostPlatform: "ubuntu26.04" + archSuffix, isOfficiallySupportedPlatform: isUbuntu && version3 === "26.04" }; + return { hostPlatform: "ubuntu" + distroInfo.version + archSuffix, isOfficiallySupportedPlatform: false }; + } + if (distroInfo?.id === "linuxmint") { + const mintMajor = parseInt(distroInfo.version, 10); + if (mintMajor <= 20) + return { hostPlatform: "ubuntu20.04" + archSuffix, isOfficiallySupportedPlatform: false }; + if (mintMajor === 21) + return { hostPlatform: "ubuntu22.04" + archSuffix, isOfficiallySupportedPlatform: false }; + return { hostPlatform: "ubuntu24.04" + archSuffix, isOfficiallySupportedPlatform: false }; + } + if (distroInfo?.id === "debian" || distroInfo?.id === "raspbian") { + const isOfficiallySupportedPlatform2 = distroInfo?.id === "debian"; + if (distroInfo?.version === "11") + return { hostPlatform: "debian11" + archSuffix, isOfficiallySupportedPlatform: isOfficiallySupportedPlatform2 }; + if (distroInfo?.version === "12") + return { hostPlatform: "debian12" + archSuffix, isOfficiallySupportedPlatform: isOfficiallySupportedPlatform2 }; + if (distroInfo?.version === "13") + return { hostPlatform: "debian13" + archSuffix, isOfficiallySupportedPlatform: isOfficiallySupportedPlatform2 }; + if (distroInfo?.version === "") + return { hostPlatform: "debian13" + archSuffix, isOfficiallySupportedPlatform: isOfficiallySupportedPlatform2 }; + } + return { hostPlatform: "ubuntu24.04" + archSuffix, isOfficiallySupportedPlatform: false }; + } + if (platform === "win32") + return { hostPlatform: "win64", isOfficiallySupportedPlatform: true }; + return { hostPlatform: "", isOfficiallySupportedPlatform: false }; +} +function toShortPlatform(hostPlatform2) { + if (hostPlatform2 === "") + return ""; + if (hostPlatform2 === "win64") + return "win-x64"; + if (hostPlatform2.startsWith("mac")) + return hostPlatform2.endsWith("arm64") ? "mac-arm64" : "mac-x64"; + return hostPlatform2.endsWith("arm64") ? "linux-arm64" : "linux-x64"; +} +var import_os3, hostPlatform, isOfficiallySupportedPlatform, shortPlatform; +var init_hostPlatform = __esm({ + "packages/utils/hostPlatform.ts"() { + "use strict"; + import_os3 = __toESM(require("os")); + init_linuxUtils(); + ({ hostPlatform, isOfficiallySupportedPlatform } = calculatePlatform()); + shortPlatform = toShortPlatform(hostPlatform); + } +}); + +// packages/utils/happyEyeballs.ts +async function createSocket(host, port) { + return new Promise((resolve, reject) => { + if (import_net.default.isIP(host)) { + const socket = import_net.default.createConnection({ host, port }); + socket.on("connect", () => resolve(socket)); + socket.on("error", (error) => reject(error)); + } else { + createConnectionAsync( + { host, port }, + (err, socket) => { + if (err) + reject(err); + if (socket) + resolve(socket); + }, + /* useTLS */ + false + ).catch((err) => reject(err)); + } + }); +} +async function createConnectionAsync(options, oncreate, useTLS) { + const lookup = options.__testHookLookup || lookupAddresses; + const hostname = clientRequestArgsToHostName(options); + const addresses = await lookup(hostname); + const dnsLookupAt = monotonicTime(); + const sockets = /* @__PURE__ */ new Set(); + let firstError; + let errorCount = 0; + const handleError = (socket, err) => { + if (!sockets.delete(socket)) + return; + ++errorCount; + firstError ??= err; + if (errorCount === addresses.length) + oncreate?.(firstError); + }; + const connected = new ManualPromise(); + for (const { address } of addresses) { + const socket = useTLS ? import_tls.default.connect({ + ...options, + port: options.port, + host: address, + servername: hostname + }) : import_net.default.createConnection({ + ...options, + port: options.port, + host: address + }); + socket[kDNSLookupAt] = dnsLookupAt; + socket.on("connect", () => { + socket[kTCPConnectionAt] = monotonicTime(); + connected.resolve(); + oncreate?.(null, socket); + sockets.delete(socket); + for (const s of sockets) + s.destroy(); + sockets.clear(); + }); + socket.on("timeout", () => { + socket.destroy(); + handleError(socket, new Error("Connection timeout")); + }); + socket.on("error", (e) => handleError(socket, e)); + sockets.add(socket); + await Promise.race([ + connected, + new Promise((f) => setTimeout(f, connectionAttemptDelayMs)) + ]); + if (connected.isDone()) + break; + } +} +async function lookupAddresses(hostname) { + const [v4Result, v6Result] = await Promise.allSettled([ + import_dns.default.promises.lookup(hostname, { all: true, family: 4 }), + import_dns.default.promises.lookup(hostname, { all: true, family: 6 }) + ]); + const v4Addresses = v4Result.status === "fulfilled" ? v4Result.value : []; + const v6Addresses = v6Result.status === "fulfilled" ? v6Result.value : []; + if (!v4Addresses.length && !v6Addresses.length) { + if (v4Result.status === "rejected") + throw v4Result.reason; + throw v6Result.reason; + } + const result2 = []; + for (let i = 0; i < Math.max(v4Addresses.length, v6Addresses.length); i++) { + if (v6Addresses[i]) + result2.push(v6Addresses[i]); + if (v4Addresses[i]) + result2.push(v4Addresses[i]); + } + return result2; +} +function clientRequestArgsToHostName(options) { + if (options.hostname) + return options.hostname; + if (options.host) + return options.host; + throw new Error("Either options.hostname or options.host must be provided"); +} +function timingForSocket(socket) { + return { + dnsLookupAt: socket[kDNSLookupAt], + tcpConnectionAt: socket[kTCPConnectionAt] + }; +} +var import_dns, import_http, import_https, import_net, import_tls, connectionAttemptDelayMs, kDNSLookupAt, kTCPConnectionAt, HttpHappyEyeballsAgent, HttpsHappyEyeballsAgent, httpsHappyEyeballsAgent, httpHappyEyeballsAgent; +var init_happyEyeballs = __esm({ + "packages/utils/happyEyeballs.ts"() { + "use strict"; + import_dns = __toESM(require("dns")); + import_http = __toESM(require("http")); + import_https = __toESM(require("https")); + import_net = __toESM(require("net")); + import_tls = __toESM(require("tls")); + init_assert(); + init_manualPromise(); + init_time(); + connectionAttemptDelayMs = 300; + kDNSLookupAt = Symbol("kDNSLookupAt"); + kTCPConnectionAt = Symbol("kTCPConnectionAt"); + HttpHappyEyeballsAgent = class extends import_http.default.Agent { + createConnection(options, oncreate) { + if (import_net.default.isIP(clientRequestArgsToHostName(options))) + return import_net.default.createConnection(options); + createConnectionAsync( + options, + oncreate, + /* useTLS */ + false + ).catch((err) => oncreate?.(err)); + } + }; + HttpsHappyEyeballsAgent = class extends import_https.default.Agent { + createConnection(options, oncreate) { + if (import_net.default.isIP(clientRequestArgsToHostName(options))) + return import_tls.default.connect(options); + createConnectionAsync( + options, + oncreate, + /* useTLS */ + true + ).catch((err) => oncreate?.(err)); + } + }; + httpsHappyEyeballsAgent = new HttpsHappyEyeballsAgent({ keepAlive: true }); + httpHappyEyeballsAgent = new HttpHappyEyeballsAgent({ keepAlive: true }); + } +}); + +// packages/utils/network.ts +function httpRequest(params2, onResponse, onError) { + let url2 = new URL(params2.url); + const options = { + method: params2.method || "GET", + headers: params2.headers + }; + if (params2.rejectUnauthorized !== void 0) + options.rejectUnauthorized = params2.rejectUnauthorized; + const proxyURL = getProxyForUrl(params2.url); + if (proxyURL) { + const parsedProxyURL = normalizeProxyURL(proxyURL); + if (params2.url.startsWith("http:")) { + options.path = url2.toString(); + const headers = options.headers || {}; + if (!Object.keys(headers).some((header) => header.toLowerCase() === "host")) + headers.host = url2.host; + options.headers = headers; + url2 = parsedProxyURL; + } else { + options.agent = new HttpsProxyAgent(parsedProxyURL); + } + } + options.agent ??= url2.protocol === "https:" ? httpsHappyEyeballsAgent : httpHappyEyeballsAgent; + let cancelRequest; + const requestCallback = (res) => { + const statusCode = res.statusCode || 0; + if (statusCode >= 300 && statusCode < 400 && res.headers.location) { + request2.destroy(); + cancelRequest = httpRequest({ ...params2, url: new URL(res.headers.location, params2.url).toString() }, onResponse, onError).cancel; + } else { + onResponse(res); + } + }; + const request2 = url2.protocol === "https:" ? import_https2.default.request(url2, options, requestCallback) : import_http2.default.request(url2, options, requestCallback); + request2.on("error", onError); + if (params2.socketTimeout !== void 0) { + request2.setTimeout(params2.socketTimeout, () => { + onError(new Error(`Request to ${params2.url} timed out after ${params2.socketTimeout}ms`)); + request2.abort(); + }); + } + cancelRequest = (e) => { + try { + request2.destroy(e); + } catch { + } + }; + request2.end(params2.data); + return { cancel: (e) => cancelRequest(e) }; +} +function shouldBypassProxy(url2, bypass) { + if (!bypass) + return false; + const domains = bypass.split(",").map((s) => { + s = s.trim(); + if (!s.startsWith(".")) + s = "." + s; + return s; + }); + const domain = "." + url2.hostname; + return domains.some((d) => domain.endsWith(d)); +} +function normalizeProxyURL(proxy) { + proxy = proxy.trim(); + if (!/^\w+:\/\//.test(proxy)) + proxy = "http://" + proxy; + return new URL(proxy); +} +function createProxyAgent(proxy, forUrl) { + if (!proxy) + return; + if (forUrl && proxy.bypass && shouldBypassProxy(forUrl, proxy.bypass)) + return; + const proxyURL = normalizeProxyURL(proxy.server); + if (proxyURL.protocol?.startsWith("socks")) { + if (proxyURL.protocol === "socks5:") + proxyURL.protocol = "socks5h:"; + else if (proxyURL.protocol === "socks4:") + proxyURL.protocol = "socks4a:"; + return new SocksProxyAgent(proxyURL); + } + if (proxy.username) { + proxyURL.username = proxy.username; + proxyURL.password = proxy.password || ""; + } + if (forUrl && ["ws:", "wss:"].includes(forUrl.protocol)) { + return new HttpsProxyAgent(proxyURL); + } + return new HttpsProxyAgent(proxyURL); +} +function createHttpServer(...args) { + const server = import_http2.default.createServer(...args); + decorateServer(server); + return server; +} +function createHttpsServer(...args) { + const server = import_https2.default.createServer(...args); + decorateServer(server); + return server; +} +function createHttp2Server(...args) { + const server = import_http22.default.createSecureServer(...args); + decorateServer(server); + return server; +} +async function startHttpServer(server, options) { + const { host = "localhost", port = 0 } = options; + const errorPromise = new ManualPromise(); + const errorListener = (error) => errorPromise.reject(error); + server.on("error", errorListener); + try { + server.listen(port, host); + await Promise.race([ + new Promise((cb) => server.once("listening", cb)), + errorPromise + ]); + } finally { + server.removeListener("error", errorListener); + } +} +async function isURLAvailable(url2, ignoreHTTPSErrors, onLog, onStdErr) { + let statusCode = await httpStatusCode(url2, ignoreHTTPSErrors, onLog, onStdErr); + if (statusCode === 404 && url2.pathname === "/") { + const indexUrl = new URL(url2); + indexUrl.pathname = "/index.html"; + statusCode = await httpStatusCode(indexUrl, ignoreHTTPSErrors, onLog, onStdErr); + } + return statusCode >= 200 && statusCode < 404; +} +async function httpStatusCode(url2, ignoreHTTPSErrors, onLog, onStdErr) { + return new Promise((resolve) => { + onLog?.(`HTTP GET: ${url2}`); + httpRequest({ + url: url2.toString(), + headers: { Accept: "*/*" }, + rejectUnauthorized: !ignoreHTTPSErrors + }, (res) => { + res.resume(); + const statusCode = res.statusCode ?? 0; + onLog?.(`HTTP Status: ${statusCode}`); + resolve(statusCode); + }, (error) => { + if (error.code === "DEPTH_ZERO_SELF_SIGNED_CERT") + onStdErr?.(`[WebServer] Self-signed certificate detected. Try adding ignoreHTTPSErrors: true to config.webServer.`); + onLog?.(`Error while checking if ${url2} is available: ${error.message}`); + resolve(0); + }); + }); +} +function decorateServer(server) { + const sockets = /* @__PURE__ */ new Set(); + server.on("connection", (socket) => { + sockets.add(socket); + socket.once("close", () => sockets.delete(socket)); + }); + const close3 = server.close; + server.close = (callback) => { + for (const socket of sockets) + socket.destroy(); + sockets.clear(); + return close3.call(server, callback); + }; +} +var import_http2, import_http22, import_https2, HttpsProxyAgent, SocksProxyAgent, getProxyForUrl, NET_DEFAULT_TIMEOUT; +var init_network = __esm({ + "packages/utils/network.ts"() { + "use strict"; + import_http2 = __toESM(require("http")); + import_http22 = __toESM(require("http2")); + import_https2 = __toESM(require("https")); + init_manualPromise(); + init_happyEyeballs(); + ({ HttpsProxyAgent } = require("./utilsBundle")); + ({ SocksProxyAgent } = require("./utilsBundle")); + ({ getProxyForUrl } = require("./utilsBundle")); + NET_DEFAULT_TIMEOUT = 3e4; + } +}); + +// packages/utils/httpServer.ts +function computeAllowedHosts(requested, bound) { + const loopback = /* @__PURE__ */ new Set(["127.0.0.1", "::1", "localhost"]); + const isLoopback = (h) => h !== void 0 && loopback.has(h.toLowerCase()); + if (!isLoopback(requested) && requested !== void 0) + return null; + if (!isLoopback(bound) && requested === void 0) + return null; + return /* @__PURE__ */ new Set(["localhost", "127.0.0.1", "[::1]"]); +} +function urlHostFromAddress(address) { + return address.family === "IPv6" ? `[${address.address}]` : address.address; +} +function hostnameFromHostHeader(host) { + if (host.startsWith("[")) { + const end = host.indexOf("]"); + return end < 0 ? host : host.substring(0, end + 1); + } + const colon = host.indexOf(":"); + return colon < 0 ? host : host.substring(0, colon); +} +function serveFolder(folder) { + const server = new HttpServer(folder); + server.routePrefix("/", (request2, response2) => { + let relativePath = new URL("http://localhost" + request2.url).pathname; + if (relativePath.startsWith("/trace/file")) { + const url2 = new URL("http://localhost" + request2.url); + const requested = url2.searchParams.get("path"); + if (!requested) + return false; + const resolved = import_path3.default.resolve(requested); + try { + return server.serveFile(request2, response2, resolved); + } catch (e) { + return false; + } + } + if (relativePath === "/") + relativePath = "/index.html"; + const absolutePath = import_path3.default.join(folder, ...relativePath.split("/")); + return server.serveFile(request2, response2, absolutePath); + }); + return server; +} +var import_fs4, import_path3, mime, wsServer, HttpServer; +var init_httpServer = __esm({ + "packages/utils/httpServer.ts"() { + "use strict"; + import_fs4 = __toESM(require("fs")); + import_path3 = __toESM(require("path")); + init_assert(); + init_crypto(); + init_fileUtils(); + init_network(); + mime = require("./utilsBundle").mime; + ({ wsServer } = require("./utilsBundle")); + HttpServer = class { + constructor(staticRoot) { + this._urlPrefixPrecise = ""; + this._urlPrefixHumanReadable = ""; + this._port = 0; + this._started = false; + this._routes = []; + // Allowed Host headers; null disables the check (host bound to a public address). + this._allowedHosts = null; + this._server = createHttpServer(this._onRequest.bind(this)); + this._staticRoot = staticRoot ? import_path3.default.resolve(staticRoot) : void 0; + } + server() { + return this._server; + } + routePrefix(prefix, handler) { + this._routes.push({ prefix, handler }); + } + routePath(path59, handler) { + this._routes.push({ exact: path59, handler }); + } + port() { + return this._port; + } + createWebSocket(transportFactory, guid) { + assert(!this._wsGuid, "can only create one main websocket transport per server"); + this._wsGuid = guid || createGuid(); + const wsPath = "/" + this._wsGuid; + const wss = new wsServer({ noServer: true }); + this._server.on("upgrade", (request2, socket, head) => { + const pathname = new URL(request2.url ?? "/", "http://localhost").pathname; + if (pathname !== wsPath) + return; + wss.handleUpgrade(request2, socket, head, (ws4) => wss.emit("connection", ws4, request2)); + }); + wss.on("connection", (ws4, request2) => { + const url2 = new URL(request2.url ?? "/", "http://localhost"); + const transport = transportFactory(url2); + transport.sendEvent = (method, params2) => ws4.send(JSON.stringify({ method, params: params2 })); + transport.close = () => ws4.close(); + transport.onconnect(); + ws4.on("message", async (message) => { + const { id, method, params: params2 } = JSON.parse(String(message)); + try { + const result2 = await transport.dispatch(method, params2); + ws4.send(JSON.stringify({ id, result: result2 })); + } catch (e) { + ws4.send(JSON.stringify({ id, error: String(e) })); + } + }); + ws4.on("close", () => transport.onclose()); + ws4.on("error", () => transport.onclose()); + }); + } + wsGuid() { + return this._wsGuid; + } + async createViteDevServer(options) { + const loadVite = new Function('return import("vite")'); + const vite = await loadVite(); + return await vite.createServer({ + root: options.root, + base: options.base, + server: { + middlewareMode: true, + // Dedicated path so Vite's HMR websocket does not collide with any + // websocket HttpServer owns via createWebSocket(). + hmr: { path: "/__vite_hmr", server: this._server } + }, + appType: "spa", + clearScreen: false + }); + } + // HMR end + // Vite's middleware `next` callback for the "no middleware matched" case; + // emits a 404 only if nothing downstream already responded. + static notFoundFallback(response2) { + return () => { + if (!response2.headersSent) { + response2.statusCode = 404; + response2.end(); + } + }; + } + async start(options = {}) { + assert(!this._started, "server already started"); + this._started = true; + const host = options.host; + if (options.preferredPort) { + try { + await startHttpServer(this._server, { port: options.preferredPort, host }); + } catch (e) { + if (!e || !e.message || !e.message.includes("EADDRINUSE")) + throw e; + await startHttpServer(this._server, { host }); + } + } else { + await startHttpServer(this._server, { port: options.port, host }); + } + const address = this._server.address(); + assert(address, "Could not bind server socket"); + if (typeof address === "string") { + this._urlPrefixPrecise = address; + this._urlPrefixHumanReadable = address; + } else { + this._port = address.port; + this._urlPrefixPrecise = `http://${urlHostFromAddress(address)}:${address.port}`; + this._urlPrefixHumanReadable = `http://${host ?? "localhost"}:${address.port}`; + this._allowedHosts = computeAllowedHosts(host, address.address); + } + } + async stop() { + await new Promise((cb) => this._server.close(cb)); + } + urlPrefix(purpose) { + return purpose === "human-readable" ? this._urlPrefixHumanReadable : this._urlPrefixPrecise; + } + serveFile(request2, response2, absoluteFilePath, headers, options) { + if (this._staticRoot && !options?.skipRootCheck && !isPathInside(this._staticRoot, absoluteFilePath)) { + response2.statusCode = 403; + response2.end(); + return true; + } + try { + for (const [name, value2] of Object.entries(headers || {})) + response2.setHeader(name, value2); + if (request2.headers.range) + this._serveRangeFile(request2, response2, absoluteFilePath); + else + this._serveFile(response2, absoluteFilePath); + return true; + } catch (e) { + return false; + } + } + _serveFile(response2, absoluteFilePath) { + const content = import_fs4.default.readFileSync(absoluteFilePath); + response2.statusCode = 200; + const contentType = mime.getType(import_path3.default.extname(absoluteFilePath)) || "application/octet-stream"; + response2.setHeader("Content-Type", contentType); + response2.setHeader("Content-Length", content.byteLength); + response2.end(content); + } + _serveRangeFile(request2, response2, absoluteFilePath) { + const range = request2.headers.range; + if (!range || !range.startsWith("bytes=") || range.includes(", ") || [...range].filter((char) => char === "-").length !== 1) { + response2.statusCode = 400; + return response2.end("Bad request"); + } + const [startStr, endStr] = range.replace(/bytes=/, "").split("-"); + let start3; + let end; + const size = import_fs4.default.statSync(absoluteFilePath).size; + if (startStr !== "" && endStr === "") { + start3 = +startStr; + end = size - 1; + } else if (startStr === "" && endStr !== "") { + start3 = size - +endStr; + end = size - 1; + } else { + start3 = +startStr; + end = +endStr; + } + if (Number.isNaN(start3) || Number.isNaN(end) || start3 >= size || end >= size || start3 > end) { + response2.writeHead(416, { + "Content-Range": `bytes */${size}` + }); + return response2.end(); + } + response2.writeHead(206, { + "Content-Range": `bytes ${start3}-${end}/${size}`, + "Accept-Ranges": "bytes", + "Content-Length": end - start3 + 1, + "Content-Type": mime.getType(import_path3.default.extname(absoluteFilePath)) + }); + const readable = import_fs4.default.createReadStream(absoluteFilePath, { start: start3, end }); + readable.pipe(response2); + } + _onRequest(request2, response2) { + if (request2.method === "OPTIONS") { + response2.writeHead(200); + response2.end(); + return; + } + if (this._allowedHosts) { + const host = request2.headers.host?.toLowerCase(); + const hostname = host ? hostnameFromHostHeader(host) : void 0; + if (!hostname || !this._allowedHosts.has(hostname)) { + response2.statusCode = 403; + response2.end(); + return; + } + } + request2.on("error", () => response2.end()); + try { + if (!request2.url) { + response2.end(); + return; + } + const url2 = new URL("http://localhost" + request2.url); + for (const route2 of this._routes) { + if (route2.exact && url2.pathname === route2.exact && route2.handler(request2, response2)) + return; + if (route2.prefix && url2.pathname.startsWith(route2.prefix) && route2.handler(request2, response2)) + return; + } + response2.statusCode = 404; + response2.end(); + } catch (e) { + response2.end(); + } + } + }; + } +}); + +// packages/utils/zones.ts +function currentZone() { + return asyncLocalStorage.getStore() ?? emptyZone; +} +var import_async_hooks, asyncLocalStorage, Zone, emptyZone; +var init_zones = __esm({ + "packages/utils/zones.ts"() { + "use strict"; + import_async_hooks = require("async_hooks"); + asyncLocalStorage = new import_async_hooks.AsyncLocalStorage(); + Zone = class _Zone { + constructor(asyncLocalStorage2, store) { + this._asyncLocalStorage = asyncLocalStorage2; + this._data = store; + } + with(type3, data) { + return new _Zone(this._asyncLocalStorage, new Map(this._data).set(type3, data)); + } + without(type3) { + const data = type3 ? new Map(this._data) : /* @__PURE__ */ new Map(); + data.delete(type3); + return new _Zone(this._asyncLocalStorage, data); + } + run(func) { + return this._asyncLocalStorage.run(this, func); + } + data(type3) { + return this._data.get(type3); + } + }; + emptyZone = new Zone(asyncLocalStorage, /* @__PURE__ */ new Map()); + } +}); + +// packages/utils/nodePlatform.ts +function setBoxedStackPrefixes(prefixes) { + boxedStackPrefixes = prefixes; +} +var import_crypto4, import_fs5, import_path4, util, import_stream, import_events, colors2, pipelineAsync, NodeZone, boxedStackPrefixes, nodePlatform, ReadableStreamImpl, WritableStreamImpl; +var init_nodePlatform = __esm({ + "packages/utils/nodePlatform.ts"() { + "use strict"; + import_crypto4 = __toESM(require("crypto")); + import_fs5 = __toESM(require("fs")); + import_path4 = __toESM(require("path")); + util = __toESM(require("util")); + import_stream = require("stream"); + import_events = require("events"); + init_debugLogger(); + init_zones(); + init_debug(); + colors2 = require("./utilsBundle").colors; + pipelineAsync = util.promisify(import_stream.pipeline); + NodeZone = class _NodeZone { + constructor(zone) { + this._zone = zone; + } + push(data) { + return new _NodeZone(this._zone.with("apiZone", data)); + } + pop() { + return new _NodeZone(this._zone.without("apiZone")); + } + run(func) { + return this._zone.run(func); + } + data() { + return this._zone.data("apiZone"); + } + }; + boxedStackPrefixes = []; + nodePlatform = (coreDir) => ({ + name: "node", + boxedStackPrefixes: () => { + if (process.env.PWDEBUGIMPL) + return []; + return [coreDir, ...boxedStackPrefixes]; + }, + calculateSha1: (text2) => { + const sha1 = import_crypto4.default.createHash("sha1"); + sha1.update(text2); + return Promise.resolve(sha1.digest("hex")); + }, + colors: colors2, + coreDir, + createGuid: () => import_crypto4.default.randomBytes(16).toString("hex"), + defaultMaxListeners: () => import_events.EventEmitter.defaultMaxListeners, + fs: () => import_fs5.default, + env: process.env, + inspectCustom: util.inspect.custom, + isDebugMode: () => debugMode() === "inspector", + isJSDebuggerAttached: () => !!require("inspector").url(), + isLogEnabled(name) { + return debugLogger.isEnabled(name); + }, + isUnderTest: () => isUnderTest(), + log(name, message) { + debugLogger.log(name, message); + }, + path: () => import_path4.default, + pathSeparator: import_path4.default.sep, + showInternalStackFrames: () => !!process.env.PWDEBUGIMPL, + async streamFile(path59, stream3) { + await pipelineAsync(import_fs5.default.createReadStream(path59), stream3); + }, + streamReadable: (channel) => { + return new ReadableStreamImpl(channel); + }, + streamWritable: (channel) => { + return new WritableStreamImpl(channel); + }, + zones: { + current: () => new NodeZone(currentZone()), + empty: new NodeZone(emptyZone) + } + }); + ReadableStreamImpl = class extends import_stream.Readable { + constructor(channel) { + super(); + this._channel = channel; + } + async _read() { + const result2 = await this._channel.read({ size: 1024 * 1024 }); + if (result2.binary.byteLength) + this.push(result2.binary); + else + this.push(null); + } + _destroy(error, callback) { + this._channel.close().catch((e) => null); + super._destroy(error, callback); + } + }; + WritableStreamImpl = class extends import_stream.Writable { + constructor(channel) { + super(); + this._channel = channel; + } + async _write(chunk, encoding, callback) { + const error = await this._channel.write({ binary: typeof chunk === "string" ? Buffer.from(chunk) : chunk }).catch((e) => e); + callback(error || null); + } + async _final(callback) { + const error = await this._channel.close().catch((e) => e); + callback(error || null); + } + }; + } +}); + +// packages/utils/processLauncher.ts +async function gracefullyCloseAll() { + await Promise.all(Array.from(gracefullyCloseSet).map((gracefullyClose) => gracefullyClose().catch((e) => { + }))); +} +function gracefullyProcessExitDoNotHang(code, onExit2) { + const beforeExit = onExit2 ? () => onExit2().catch(() => { + }) : () => Promise.resolve(); + const callback = () => beforeExit().then(() => process.exit(code)); + setTimeout(callback, 3e4); + gracefullyCloseAll().then(callback); +} +function exitHandler() { + for (const kill of killSet) + kill(); +} +function sigintHandler() { + const exitWithCode130 = () => { + if (isUnderTest()) { + setTimeout(() => process.exit(130), 1e3); + } else { + process.exit(130); + } + }; + if (sigintHandlerCalled) { + process.off("SIGINT", sigintHandler); + for (const kill of killSet) + kill(); + exitWithCode130(); + } else { + sigintHandlerCalled = true; + gracefullyCloseAll().then(() => exitWithCode130()); + } +} +function sigtermHandler() { + gracefullyCloseAll(); +} +function sighupHandler() { + gracefullyCloseAll(); +} +function addProcessHandlerIfNeeded(name) { + if (!installedHandlers.has(name)) { + installedHandlers.add(name); + process.on(name, processHandlers[name]); + } +} +function removeProcessHandlersIfNeeded() { + if (killSet.size) + return; + for (const handler of installedHandlers) + process.off(handler, processHandlers[handler]); + installedHandlers.clear(); +} +async function launchProcess(options) { + const stdio = options.stdio === "pipe" ? ["ignore", "pipe", "pipe", "pipe", "pipe"] : ["pipe", "pipe", "pipe"]; + options.log(` ${options.command} ${options.args ? options.args.join(" ") : ""}`); + const spawnOptions = { + // On non-windows platforms, `detached: true` makes child process a leader of a new + // process group, making it possible to kill child process tree with `.kill(-pid)` command. + // @see https://nodejs.org/api/child_process.html#child_process_options_detached + detached: process.platform !== "win32", + env: options.env, + cwd: options.cwd, + shell: options.shell, + stdio + }; + const spawnedProcess = childProcess.spawn(options.command, options.args || [], spawnOptions); + const cleanup = async () => { + options.log(`[pid=${spawnedProcess.pid || "N/A"}] starting temporary directories cleanup`); + const errors = await removeFolders(options.tempDirectories); + for (let i = 0; i < options.tempDirectories.length; ++i) { + if (errors[i]) + options.log(`[pid=${spawnedProcess.pid || "N/A"}] exception while removing ${options.tempDirectories[i]}: ${errors[i]}`); + } + options.log(`[pid=${spawnedProcess.pid || "N/A"}] finished temporary directories cleanup`); + }; + spawnedProcess.on("error", () => { + }); + if (!spawnedProcess.pid) { + let failed; + const failedPromise = new Promise((f, r) => failed = f); + spawnedProcess.once("error", (error) => { + failed(new Error("Failed to launch: " + error)); + }); + return failedPromise.then(async (error) => { + await cleanup(); + throw error; + }); + } + options.log(` pid=${spawnedProcess.pid}`); + const stdout = readline.createInterface({ input: spawnedProcess.stdout }); + stdout.on("line", (data) => { + options.log(`[pid=${spawnedProcess.pid}][out] ` + data); + }); + const stderr = readline.createInterface({ input: spawnedProcess.stderr }); + stderr.on("line", (data) => { + options.log(`[pid=${spawnedProcess.pid}][err] ` + data); + }); + let processClosed = false; + let fulfillCleanup = () => { + }; + const waitForCleanup = new Promise((f) => fulfillCleanup = f); + spawnedProcess.once("close", (exitCode, signal) => { + options.log(`[pid=${spawnedProcess.pid}] `); + processClosed = true; + gracefullyCloseSet.delete(gracefullyClose); + killSet.delete(killProcessAndCleanup); + removeProcessHandlersIfNeeded(); + options.onExit(exitCode, signal); + cleanup().then(fulfillCleanup); + }); + addProcessHandlerIfNeeded("exit"); + if (options.handleSIGINT) + addProcessHandlerIfNeeded("SIGINT"); + if (options.handleSIGTERM) + addProcessHandlerIfNeeded("SIGTERM"); + if (options.handleSIGHUP) + addProcessHandlerIfNeeded("SIGHUP"); + gracefullyCloseSet.add(gracefullyClose); + killSet.add(killProcessAndCleanup); + let gracefullyClosing = false; + async function gracefullyClose() { + if (gracefullyClosing) { + options.log(`[pid=${spawnedProcess.pid}] `); + killProcess(); + await waitForCleanup; + return; + } + gracefullyClosing = true; + options.log(`[pid=${spawnedProcess.pid}] `); + await options.attemptToGracefullyClose().catch(() => killProcess()); + await waitForCleanup; + options.log(`[pid=${spawnedProcess.pid}] `); + } + function killProcess() { + gracefullyCloseSet.delete(gracefullyClose); + killSet.delete(killProcessAndCleanup); + removeProcessHandlersIfNeeded(); + options.log(`[pid=${spawnedProcess.pid}] `); + if (spawnedProcess.pid && !spawnedProcess.killed && !processClosed) { + options.log(`[pid=${spawnedProcess.pid}] `); + try { + if (process.platform === "win32") { + const taskkillProcess = childProcess.spawnSync(`taskkill /pid ${spawnedProcess.pid} /T /F`, { shell: true }); + const [stdout2, stderr2] = [taskkillProcess.stdout.toString(), taskkillProcess.stderr.toString()]; + if (stdout2) + options.log(`[pid=${spawnedProcess.pid}] taskkill stdout: ${stdout2}`); + if (stderr2) + options.log(`[pid=${spawnedProcess.pid}] taskkill stderr: ${stderr2}`); + } else { + process.kill(-spawnedProcess.pid, "SIGKILL"); + } + } catch (e) { + options.log(`[pid=${spawnedProcess.pid}] exception while trying to kill process: ${e}`); + } + } else { + options.log(`[pid=${spawnedProcess.pid}] `); + } + } + function killProcessAndCleanup() { + killProcess(); + options.log(`[pid=${spawnedProcess.pid || "N/A"}] starting temporary directories cleanup`); + for (const dir of options.tempDirectories) { + try { + import_fs6.default.rmSync(dir, { force: true, recursive: true, maxRetries: 5 }); + } catch (e) { + options.log(`[pid=${spawnedProcess.pid || "N/A"}] exception while removing ${dir}: ${e}`); + } + } + options.log(`[pid=${spawnedProcess.pid || "N/A"}] finished temporary directories cleanup`); + } + function killAndWait() { + killProcess(); + return waitForCleanup; + } + return { launchedProcess: spawnedProcess, gracefullyClose, kill: killAndWait }; +} +function envArrayToObject(env) { + const result2 = {}; + for (const { name, value: value2 } of env) + result2[name] = value2; + return result2; +} +var childProcess, import_fs6, readline, gracefullyCloseSet, killSet, sigintHandlerCalled, installedHandlers, processHandlers; +var init_processLauncher = __esm({ + "packages/utils/processLauncher.ts"() { + "use strict"; + childProcess = __toESM(require("child_process")); + import_fs6 = __toESM(require("fs")); + readline = __toESM(require("readline")); + init_fileUtils(); + init_debug(); + gracefullyCloseSet = /* @__PURE__ */ new Set(); + killSet = /* @__PURE__ */ new Set(); + sigintHandlerCalled = false; + installedHandlers = /* @__PURE__ */ new Set(); + processHandlers = { + exit: exitHandler, + SIGINT: sigintHandler, + SIGTERM: sigtermHandler, + SIGHUP: sighupHandler + }; + } +}); + +// packages/utils/profiler.ts +async function startProfiling() { + if (!profileDir) + return; + session = new (require("inspector")).Session(); + session.connect(); + await new Promise((f) => { + session.post("Profiler.enable", () => { + session.post("Profiler.start", f); + }); + }); +} +async function stopProfiling(profileName) { + if (!profileDir) + return; + await new Promise((f) => session.post("Profiler.stop", (err, { profile }) => { + if (!err) { + import_fs7.default.mkdirSync(profileDir, { recursive: true }); + import_fs7.default.writeFileSync(import_path5.default.join(profileDir, profileName + ".json"), JSON.stringify(profile)); + } + f(); + })); +} +var import_fs7, import_path5, profileDir, session; +var init_profiler = __esm({ + "packages/utils/profiler.ts"() { + "use strict"; + import_fs7 = __toESM(require("fs")); + import_path5 = __toESM(require("path")); + profileDir = process.env.PWTEST_PROFILE_DIR || ""; + } +}); + +// packages/utils/serializedFS.ts +var import_fs8, yazl, APPEND_CHUNK_SIZE, SerializedFS; +var init_serializedFS = __esm({ + "packages/utils/serializedFS.ts"() { + "use strict"; + import_fs8 = __toESM(require("fs")); + init_manualPromise(); + yazl = require("./utilsBundle").yazl; + APPEND_CHUNK_SIZE = 64 * 1024; + SerializedFS = class { + constructor() { + this._buffers = /* @__PURE__ */ new Map(); + this._operations = []; + this._operationsDone = new ManualPromise(); + this._operationsDone.resolve(); + } + mkdir(dir) { + this._appendOperation({ op: "mkdir", dir }); + } + writeFile(file, content, skipIfExists) { + this._buffers.delete(file); + this._appendOperation({ op: "writeFile", file, content, skipIfExists }); + } + appendFile(file, text2, flush) { + if (!this._buffers.has(file)) + this._buffers.set(file, []); + const buffer = this._buffers.get(file); + buffer.push(text2); + let size = 0; + for (const chunk of buffer) + size += chunk.length; + if (flush || size >= APPEND_CHUNK_SIZE) + this._flushFile(file); + } + _flushFile(file) { + const buffer = this._buffers.get(file); + if (buffer === void 0) + return; + const content = buffer.join(""); + this._buffers.delete(file); + this._appendOperation({ op: "appendFile", file, content }); + } + copyFile(from, to) { + this._flushFile(from); + this._buffers.delete(to); + this._appendOperation({ op: "copyFile", from, to }); + } + async syncAndGetError() { + for (const file of this._buffers.keys()) + this._flushFile(file); + await this._operationsDone; + return this._error; + } + zip(entries, zipFileName) { + for (const file of this._buffers.keys()) + this._flushFile(file); + this._appendOperation({ op: "zip", entries, zipFileName }); + } + // This method serializes all writes to the trace. + _appendOperation(op) { + const last = this._operations[this._operations.length - 1]; + if (last?.op === "appendFile" && op.op === "appendFile" && last.file === op.file && last.content.length < APPEND_CHUNK_SIZE) { + last.content += op.content; + return; + } + this._operations.push(op); + if (this._operationsDone.isDone()) + this._performOperations(); + } + async _performOperations() { + this._operationsDone = new ManualPromise(); + while (this._operations.length) { + const op = this._operations.shift(); + if (this._error) + continue; + try { + await this._performOperation(op); + } catch (e) { + this._error = e; + } + } + this._operationsDone.resolve(); + } + async _performOperation(op) { + switch (op.op) { + case "mkdir": { + await import_fs8.default.promises.mkdir(op.dir, { recursive: true }); + return; + } + case "writeFile": { + if (op.skipIfExists) + await import_fs8.default.promises.writeFile(op.file, op.content, { flag: "wx" }).catch(() => { + }); + else + await import_fs8.default.promises.writeFile(op.file, op.content); + return; + } + case "copyFile": { + await import_fs8.default.promises.copyFile(op.from, op.to); + return; + } + case "appendFile": { + await import_fs8.default.promises.appendFile(op.file, op.content); + return; + } + case "zip": { + const zipFile = new yazl.ZipFile(); + const result2 = new ManualPromise(); + zipFile.on("error", (error) => result2.reject(error)); + for (const entry of op.entries) + zipFile.addFile(entry.value, entry.name); + zipFile.end(); + zipFile.outputStream.pipe(import_fs8.default.createWriteStream(op.zipFileName)).on("close", () => result2.resolve()).on("error", (error) => result2.reject(error)); + await result2; + return; + } + } + } + }; + } +}); + +// packages/utils/socksProxy.ts +function hexToNumber(hex) { + return [...hex].reduce((value2, digit2) => { + const code = digit2.charCodeAt(0); + if (code >= 48 && code <= 57) + return value2 + code; + if (code >= 97 && code <= 102) + return value2 + (code - 97) + 10; + if (code >= 65 && code <= 70) + return value2 + (code - 65) + 10; + throw new Error("Invalid IPv6 token " + hex); + }, 0); +} +function ipToSocksAddress(address) { + const ipv4Mapped = /^::ffff:(\d+\.\d+\.\d+\.\d+)$/i.exec(address); + if (ipv4Mapped) + address = ipv4Mapped[1]; + if (import_net2.default.isIPv4(address)) { + return [ + 1, + // IPv4 + ...address.split(".", 4).map((t) => +t & 255) + // Address + ]; + } + if (import_net2.default.isIPv6(address)) { + const result2 = [4]; + const tokens = address.split(":", 8); + while (tokens.length < 8) + tokens.unshift(""); + for (const token of tokens) { + const value2 = hexToNumber(token); + result2.push(value2 >> 8 & 255, value2 & 255); + } + return result2; + } + throw new Error("Only IPv4 and IPv6 addresses are supported"); +} +function starMatchToRegex(pattern) { + const source11 = pattern.split("*").map((s) => { + return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); + }).join(".*"); + return new RegExp("^" + source11 + "$"); +} +function parsePattern(pattern) { + if (!pattern) + return () => false; + const matchers = pattern.split(",").map((token) => { + const match = token.match(/^(.*?)(?::(\d+))?$/); + if (!match) + throw new Error(`Unsupported token "${token}" in pattern "${pattern}"`); + const tokenPort = match[2] ? +match[2] : void 0; + const portMatches = (port) => tokenPort === void 0 || tokenPort === port; + let tokenHost = match[1]; + if (tokenHost === "") { + return (host, port) => { + if (!portMatches(port)) + return false; + return host === "localhost" || host.endsWith(".localhost") || host === "127.0.0.1" || host === "[::1]"; + }; + } + if (tokenHost === "*") + return (host, port) => portMatches(port); + if (import_net2.default.isIPv4(tokenHost) || import_net2.default.isIPv6(tokenHost)) + return (host, port) => host === tokenHost && portMatches(port); + if (tokenHost[0] === ".") + tokenHost = "*" + tokenHost; + const tokenRegex = starMatchToRegex(tokenHost); + return (host, port) => { + if (!portMatches(port)) + return false; + if (import_net2.default.isIPv4(host) || import_net2.default.isIPv6(host)) + return false; + return !!host.match(tokenRegex); + }; + }); + return (host, port) => matchers.some((matcher) => matcher(host, port)); +} +var import_events2, import_net2, SocksConnection, SocksProxy, SocksProxyHandler; +var init_socksProxy = __esm({ + "packages/utils/socksProxy.ts"() { + "use strict"; + import_events2 = __toESM(require("events")); + import_net2 = __toESM(require("net")); + init_assert(); + init_crypto(); + init_debugLogger(); + init_happyEyeballs(); + SocksConnection = class { + constructor(uid, socket, client) { + this._buffer = Buffer.from([]); + this._offset = 0; + this._fence = 0; + this._uid = uid; + this._socket = socket; + this._client = client; + this._boundOnData = this._onData.bind(this); + socket.on("data", this._boundOnData); + socket.on("close", () => this._onClose()); + socket.on("end", () => this._onClose()); + socket.on("error", () => this._onClose()); + this._run().catch(() => this._socket.end()); + } + async _run() { + assert(await this._authenticate()); + const { command, host, port } = await this._parseRequest(); + if (command !== 1 /* CONNECT */) { + this._writeBytes(Buffer.from([ + 5, + 7 /* CommandNotSupported */, + 0, + // RSV + 1, + // IPv4 + 0, + 0, + 0, + 0, + // Address + 0, + 0 + // Port + ])); + return; + } + this._socket.off("data", this._boundOnData); + this._client.onSocketRequested({ uid: this._uid, host, port }); + } + async _authenticate() { + const version3 = await this._readByte(); + assert(version3 === 5, "The VER field must be set to x05 for this version of the protocol, was " + version3); + const nMethods = await this._readByte(); + assert(nMethods, "No authentication methods specified"); + const methods = await this._readBytes(nMethods); + for (const method of methods) { + if (method === 0) { + this._writeBytes(Buffer.from([version3, method])); + return true; + } + } + this._writeBytes(Buffer.from([version3, 255 /* NO_ACCEPTABLE_METHODS */])); + return false; + } + async _parseRequest() { + const version3 = await this._readByte(); + assert(version3 === 5, "The VER field must be set to x05 for this version of the protocol, was " + version3); + const command = await this._readByte(); + await this._readByte(); + const addressType = await this._readByte(); + let host = ""; + switch (addressType) { + case 1 /* IPv4 */: + host = (await this._readBytes(4)).join("."); + break; + case 3 /* FqName */: + const length = await this._readByte(); + host = (await this._readBytes(length)).toString(); + break; + case 4 /* IPv6 */: + const bytes = await this._readBytes(16); + const tokens = []; + for (let i = 0; i < 8; ++i) + tokens.push(bytes.readUInt16BE(i * 2).toString(16)); + host = tokens.join(":"); + break; + } + const port = (await this._readBytes(2)).readUInt16BE(0); + this._buffer = Buffer.from([]); + this._offset = 0; + this._fence = 0; + return { + command, + host, + port + }; + } + async _readByte() { + const buffer = await this._readBytes(1); + return buffer[0]; + } + async _readBytes(length) { + this._fence = this._offset + length; + if (!this._buffer || this._buffer.length < this._fence) + await new Promise((f) => this._fenceCallback = f); + this._offset += length; + return this._buffer.slice(this._offset - length, this._offset); + } + _writeBytes(buffer) { + if (this._socket.writable) + this._socket.write(buffer); + } + _onClose() { + this._client.onSocketClosed({ uid: this._uid }); + } + _onData(buffer) { + this._buffer = Buffer.concat([this._buffer, buffer]); + if (this._fenceCallback && this._buffer.length >= this._fence) { + const callback = this._fenceCallback; + this._fenceCallback = void 0; + callback(); + } + } + socketConnected(host, port) { + this._writeBytes(Buffer.from([ + 5, + 0 /* Succeeded */, + 0, + // RSV + ...ipToSocksAddress(host), + // ATYP, Address + port >> 8, + port & 255 + // Port + ])); + this._socket.on("data", (data) => this._client.onSocketData({ uid: this._uid, data })); + } + socketFailed(errorCode) { + const buffer = Buffer.from([ + 5, + 0, + 0, + // RSV + ...ipToSocksAddress("0.0.0.0"), + // ATYP, Address + 0, + 0 + // Port + ]); + switch (errorCode) { + case "ENOENT": + case "ENOTFOUND": + case "ETIMEDOUT": + case "EHOSTUNREACH": + buffer[1] = 4 /* HostUnreachable */; + break; + case "ENETUNREACH": + buffer[1] = 3 /* NetworkUnreachable */; + break; + case "ECONNREFUSED": + buffer[1] = 5 /* ConnectionRefused */; + break; + case "ERULESET": + buffer[1] = 2 /* NotAllowedByRuleSet */; + break; + } + this._writeBytes(buffer); + this._socket.end(); + } + sendData(data) { + this._socket.write(data); + } + end() { + this._socket.end(); + } + error(error) { + this._socket.destroy(new Error(error)); + } + }; + SocksProxy = class _SocksProxy extends import_events2.default { + constructor() { + super(); + this._connections = /* @__PURE__ */ new Map(); + this._sockets = /* @__PURE__ */ new Set(); + this._closed = false; + this._patternMatcher = () => false; + this._directSockets = /* @__PURE__ */ new Map(); + this._server = new import_net2.default.Server((socket) => { + const uid = createGuid(); + const connection = new SocksConnection(uid, socket, this); + this._connections.set(uid, connection); + }); + this._server.on("connection", (socket) => { + if (this._closed) { + socket.destroy(); + return; + } + this._sockets.add(socket); + socket.once("close", () => this._sockets.delete(socket)); + }); + } + static { + this.Events = { + SocksRequested: "socksRequested", + SocksData: "socksData", + SocksClosed: "socksClosed" + }; + } + setPattern(pattern) { + try { + this._patternMatcher = parsePattern(pattern); + } catch (e) { + this._patternMatcher = () => false; + } + } + async _handleDirect(request2) { + try { + const socket = await createSocket(request2.host, request2.port); + socket.on("data", (data) => this._connections.get(request2.uid)?.sendData(data)); + socket.on("error", (error) => { + this._connections.get(request2.uid)?.error(error.message); + this._directSockets.delete(request2.uid); + }); + socket.on("end", () => { + this._connections.get(request2.uid)?.end(); + this._directSockets.delete(request2.uid); + }); + const localAddress = socket.localAddress; + const localPort = socket.localPort; + this._directSockets.set(request2.uid, socket); + this._connections.get(request2.uid)?.socketConnected(localAddress, localPort); + } catch (error) { + this._connections.get(request2.uid)?.socketFailed(error.code); + } + } + port() { + return this._port; + } + async listen(port, hostname) { + return new Promise((f) => { + this._server.listen(port, hostname, () => { + const port2 = this._server.address().port; + this._port = port2; + f(port2); + }); + }); + } + async close() { + if (this._closed) + return; + this._closed = true; + for (const socket of this._sockets) + socket.destroy(); + this._sockets.clear(); + await new Promise((f) => this._server.close(f)); + } + onSocketRequested(payload) { + if (!this._patternMatcher(payload.host, payload.port)) { + this._handleDirect(payload); + return; + } + this.emit(_SocksProxy.Events.SocksRequested, payload); + } + onSocketData(payload) { + const direct = this._directSockets.get(payload.uid); + if (direct) { + direct.write(payload.data); + return; + } + this.emit(_SocksProxy.Events.SocksData, payload); + } + onSocketClosed(payload) { + const direct = this._directSockets.get(payload.uid); + if (direct) { + direct.destroy(); + this._directSockets.delete(payload.uid); + return; + } + this.emit(_SocksProxy.Events.SocksClosed, payload); + } + socketConnected({ uid, host, port }) { + this._connections.get(uid)?.socketConnected(host, port); + } + socketFailed({ uid, errorCode }) { + this._connections.get(uid)?.socketFailed(errorCode); + } + sendSocketData({ uid, data }) { + this._connections.get(uid)?.sendData(data); + } + sendSocketEnd({ uid }) { + this._connections.get(uid)?.end(); + } + sendSocketError({ uid, error }) { + this._connections.get(uid)?.error(error); + } + }; + SocksProxyHandler = class _SocksProxyHandler extends import_events2.default { + constructor(pattern, redirectPortForTest) { + super(); + this._sockets = /* @__PURE__ */ new Map(); + this._patternMatcher = () => false; + this._patternMatcher = parsePattern(pattern); + this._redirectPortForTest = redirectPortForTest; + } + static { + this.Events = { + SocksConnected: "socksConnected", + SocksData: "socksData", + SocksError: "socksError", + SocksFailed: "socksFailed", + SocksEnd: "socksEnd" + }; + } + cleanup() { + for (const uid of this._sockets.keys()) + this.socketClosed({ uid }); + } + async socketRequested({ uid, host, port }) { + debugLogger.log("socks", `[${uid}] => request ${host}:${port}`); + if (!this._patternMatcher(host, port)) { + const payload = { uid, errorCode: "ERULESET" }; + debugLogger.log("socks", `[${uid}] <= pattern error ${payload.errorCode}`); + this.emit(_SocksProxyHandler.Events.SocksFailed, payload); + return; + } + if (host === "local.playwright") + host = "localhost"; + try { + if (this._redirectPortForTest) + port = this._redirectPortForTest; + const socket = await createSocket(host, port); + socket.on("data", (data) => { + const payload2 = { uid, data }; + this.emit(_SocksProxyHandler.Events.SocksData, payload2); + }); + socket.on("error", (error) => { + const payload2 = { uid, error: error.message }; + debugLogger.log("socks", `[${uid}] <= network socket error ${payload2.error}`); + this.emit(_SocksProxyHandler.Events.SocksError, payload2); + this._sockets.delete(uid); + }); + socket.on("end", () => { + const payload2 = { uid }; + debugLogger.log("socks", `[${uid}] <= network socket closed`); + this.emit(_SocksProxyHandler.Events.SocksEnd, payload2); + this._sockets.delete(uid); + }); + const localAddress = socket.localAddress; + const localPort = socket.localPort; + this._sockets.set(uid, socket); + const payload = { uid, host: localAddress, port: localPort }; + debugLogger.log("socks", `[${uid}] <= connected to network ${payload.host}:${payload.port}`); + this.emit(_SocksProxyHandler.Events.SocksConnected, payload); + } catch (error) { + const payload = { uid, errorCode: error.code }; + debugLogger.log("socks", `[${uid}] <= connect error ${payload.errorCode}`); + this.emit(_SocksProxyHandler.Events.SocksFailed, payload); + } + } + sendSocketData({ uid, data }) { + this._sockets.get(uid)?.write(data); + } + socketClosed({ uid }) { + debugLogger.log("socks", `[${uid}] <= browser socket closed`); + this._sockets.get(uid)?.destroy(); + this._sockets.delete(uid); + } + }; + } +}); + +// packages/utils/spawnAsync.ts +function spawnAsync(cmd, args, options = {}) { + const process2 = (0, import_child_process.spawn)(cmd, args, Object.assign({ windowsHide: true }, options)); + return new Promise((resolve) => { + let stdout = ""; + let stderr = ""; + if (process2.stdout) + process2.stdout.on("data", (data) => stdout += data.toString()); + if (process2.stderr) + process2.stderr.on("data", (data) => stderr += data.toString()); + process2.on("close", (code) => resolve({ stdout, stderr, code })); + process2.on("error", (error) => resolve({ stdout, stderr, code: 0, error })); + }); +} +var import_child_process; +var init_spawnAsync = __esm({ + "packages/utils/spawnAsync.ts"() { + "use strict"; + import_child_process = require("child_process"); + } +}); + +// packages/utils/stringWidth.ts +function characterWidth(c) { + return getEastAsianWidth.eastAsianWidth(c.codePointAt(0)); +} +function stringWidth(v) { + let width = 0; + for (const { segment } of new Intl.Segmenter(void 0, { granularity: "grapheme" }).segment(v)) + width += characterWidth(segment); + return width; +} +function suffixOfWidth(v, width) { + const segments = [...new Intl.Segmenter(void 0, { granularity: "grapheme" }).segment(v)]; + let suffixBegin = v.length; + for (const { segment, index } of segments.reverse()) { + const segmentWidth = stringWidth(segment); + if (segmentWidth > width) + break; + width -= segmentWidth; + suffixBegin = index; + } + return v.substring(suffixBegin); +} +function fitToWidth(line, width, prefix) { + const prefixLength = prefix ? stripAnsiEscapes(prefix).length : 0; + width -= prefixLength; + if (stringWidth(line) <= width) + return line; + const parts = line.split(ansiRegex); + const taken = []; + for (let i = parts.length - 1; i >= 0; i--) { + if (i % 2) { + taken.push(parts[i]); + } else { + let part = suffixOfWidth(parts[i], width); + const wasTruncated = part.length < parts[i].length; + if (wasTruncated && parts[i].length > 0) { + part = "\u2026" + suffixOfWidth(parts[i], width - 1); + } + taken.push(part); + width -= stringWidth(part); + } + } + return taken.reverse().join(""); +} +var getEastAsianWidth; +var init_stringWidth = __esm({ + "packages/utils/stringWidth.ts"() { + "use strict"; + init_stringUtils(); + getEastAsianWidth = require("./utilsBundle").getEastAsianWidth; + } +}); + +// packages/utils/task.ts +function makeWaitForNextTask() { + if (process.versions.electron) + return (callback) => setTimeout(callback, 0); + if (parseInt(process.versions.node, 10) >= 11) + return setImmediate; + let spinning = false; + const callbacks = []; + const loop = () => { + const callback = callbacks.shift(); + if (!callback) { + spinning = false; + return; + } + setImmediate(loop); + callback(); + }; + return (callback) => { + callbacks.push(callback); + if (!spinning) { + spinning = true; + setImmediate(loop); + } + }; +} +var init_task = __esm({ + "packages/utils/task.ts"() { + "use strict"; + } +}); + +// packages/utils/wsServer.ts +var wsServer2, lastConnectionId, kConnectionSymbol, perMessageDeflate, WSServer; +var init_wsServer = __esm({ + "packages/utils/wsServer.ts"() { + "use strict"; + init_httpServer(); + init_network(); + init_debugLogger(); + ({ wsServer: wsServer2 } = require("./utilsBundle")); + lastConnectionId = 0; + kConnectionSymbol = Symbol("kConnection"); + perMessageDeflate = { + serverNoContextTakeover: true, + zlibDeflateOptions: { + level: 3 + }, + zlibInflateOptions: { + chunkSize: 10 * 1024 + }, + threshold: 10 * 1024 + }; + WSServer = class { + constructor(delegate) { + // Allowed Host headers for HTTP requests. null disables the check (server bound to a public address). + this._allowedHosts = null; + this._delegate = delegate; + } + async listen(port = 0, hostname, path59) { + debugLogger.log("server", `Server started at ${/* @__PURE__ */ new Date()}`); + hostname ??= "localhost"; + const server = createHttpServer((request2, response2) => this._onRequest(request2, response2)); + server.on("error", (error) => debugLogger.log("server", String(error))); + this.server = server; + const wsEndpoint = await new Promise((resolve, reject) => { + server.listen(port, hostname, () => { + const address = server.address(); + if (!address) { + reject(new Error("Could not bind server socket")); + return; + } + if (typeof address === "string") { + resolve(`${address}${path59}`); + return; + } + this._allowedHosts = computeAllowedHosts(hostname, address.address); + resolve(`ws://${urlHostFromAddress(address)}:${address.port}${path59}`); + }).on("error", reject); + }); + debugLogger.log("server", "Listening at " + wsEndpoint); + this._wsServer = new wsServer2({ + noServer: true, + perMessageDeflate + }); + this._wsServer.on("headers", (headers) => this._delegate.onHeaders(headers)); + server.on("upgrade", (request2, socket, head) => { + const pathname = new URL("http://localhost" + request2.url).pathname; + if (pathname !== path59) { + socket.write(`HTTP/${request2.httpVersion} 400 Bad Request\r +\r +`); + socket.destroy(); + return; + } + if (this._allowedHosts && !this._isAllowedOrigin(request2.headers.origin)) { + socket.write(`HTTP/${request2.httpVersion} 403 Forbidden\r +\r +`); + socket.destroy(); + return; + } + const upgradeResult = this._delegate.onUpgrade(request2, socket); + if (upgradeResult) { + socket.write(upgradeResult.error); + socket.destroy(); + return; + } + this._wsServer.handleUpgrade(request2, socket, head, (ws4) => this._wsServer.emit("connection", ws4, request2)); + }); + this._wsServer.on("connection", (ws4, request2) => { + debugLogger.log("server", "Connected client ws.extension=" + ws4.extensions); + const url2 = new URL("http://localhost" + (request2.url || "")); + const id = String(++lastConnectionId); + debugLogger.log("server", `[${id}] serving connection: ${request2.url}`); + const connection = this._delegate.onConnection(request2, url2, ws4, id); + ws4[kConnectionSymbol] = connection; + }); + return wsEndpoint; + } + _onRequest(request2, response2) { + if (this._allowedHosts) { + const host = request2.headers.host?.toLowerCase(); + const hostname = host ? hostnameFromHostHeader(host) : void 0; + if (!hostname || !this._allowedHosts.has(hostname)) { + response2.statusCode = 403; + response2.end(); + return; + } + } + this._delegate.onRequest(request2, response2); + } + _isAllowedOrigin(origin) { + if (!origin) + return true; + try { + const hostname = new URL(origin).hostname.toLowerCase(); + const bracketed = hostname.includes(":") ? `[${hostname}]` : hostname; + return this._allowedHosts.has(hostname) || this._allowedHosts.has(bracketed); + } catch { + return false; + } + } + async close() { + const server = this._wsServer; + if (!server) + return; + debugLogger.log("server", "closing websocket server"); + const waitForClose = new Promise((f) => server.close(f)); + await Promise.all(Array.from(server.clients).map(async (ws4) => { + const connection = ws4[kConnectionSymbol]; + if (connection) + await connection.close(); + try { + ws4.terminate(); + } catch (e) { + } + })); + await waitForClose; + debugLogger.log("server", "closing http server"); + if (this.server) + await new Promise((f) => this.server.close(f)); + this._wsServer = void 0; + this.server = void 0; + debugLogger.log("server", "closed server"); + } + }; + } +}); + +// packages/utils/zipFile.ts +var yauzl, ZipFile; +var init_zipFile = __esm({ + "packages/utils/zipFile.ts"() { + "use strict"; + yauzl = require("./utilsBundle").yauzl; + ZipFile = class { + constructor(fileName) { + this._entries = /* @__PURE__ */ new Map(); + this._fileName = fileName; + this._openedPromise = this._open(); + } + async _open() { + await new Promise((fulfill, reject) => { + yauzl.open(this._fileName, { autoClose: false }, (e, z31) => { + if (e) { + reject(e); + return; + } + this._zipFile = z31; + this._zipFile.on("entry", (entry) => { + this._entries.set(entry.fileName, entry); + }); + this._zipFile.on("end", fulfill); + }); + }); + } + async entries() { + await this._openedPromise; + return [...this._entries.keys()]; + } + async read(entryPath) { + await this._openedPromise; + const entry = this._entries.get(entryPath); + if (!entry) + throw new Error(`${entryPath} not found in file ${this._fileName}`); + return new Promise((resolve, reject) => { + this._zipFile.openReadStream(entry, (error, readStream) => { + if (error || !readStream) { + reject(error || "Entry not found"); + return; + } + const buffers = []; + readStream.on("data", (data) => buffers.push(data)); + readStream.on("end", () => resolve(Buffer.concat(buffers))); + }); + }); + } + close() { + this._zipFile?.close(); + } + }; + } +}); + +// packages/utils/third_party/extractZip.ts +async function extractZip(zipPath, opts) { + debug2("creating target directory", opts.dir); + if (!import_path6.default.isAbsolute(opts.dir)) + throw new Error("Target directory is expected to be absolute"); + await import_fs9.promises.mkdir(opts.dir, { recursive: true }); + opts.dir = await import_fs9.promises.realpath(opts.dir); + return new Extractor(zipPath, opts).extract(); +} +var import_fs9, import_path6, import_stream2, import_util, debugPkg, getStream, yauzl2, debug2, openZip, pipeline2, Extractor; +var init_extractZip = __esm({ + "packages/utils/third_party/extractZip.ts"() { + "use strict"; + import_fs9 = require("fs"); + import_path6 = __toESM(require("path")); + import_stream2 = __toESM(require("stream")); + import_util = require("util"); + debugPkg = require("./utilsBundle").debug; + getStream = require("./utilsBundle").getStream; + yauzl2 = require("./utilsBundle").yauzl; + debug2 = debugPkg("extract-zip"); + openZip = (0, import_util.promisify)(yauzl2.open); + pipeline2 = (0, import_util.promisify)(import_stream2.default.pipeline); + Extractor = class { + constructor(zipPath, opts) { + this.canceled = false; + this.zipPath = zipPath; + this.opts = opts; + } + async extract() { + debug2("opening", this.zipPath, "with opts", this.opts); + this.zipfile = await openZip(this.zipPath, { lazyEntries: true }); + this.canceled = false; + return new Promise((resolve, reject) => { + this.zipfile.on("error", (err) => { + this.canceled = true; + reject(err); + }); + this.zipfile.readEntry(); + this.zipfile.on("close", () => { + if (!this.canceled) { + debug2("zip extraction complete"); + resolve(); + } + }); + this.zipfile.on("entry", async (entry) => { + if (this.canceled) { + debug2("skipping entry", entry.fileName, { cancelled: this.canceled }); + return; + } + debug2("zipfile entry", entry.fileName); + if (entry.fileName.startsWith("__MACOSX/")) { + this.zipfile.readEntry(); + return; + } + const destDir = import_path6.default.dirname(import_path6.default.join(this.opts.dir, entry.fileName)); + try { + await import_fs9.promises.mkdir(destDir, { recursive: true }); + const canonicalDestDir = await import_fs9.promises.realpath(destDir); + const relativeDestDir = import_path6.default.relative(this.opts.dir, canonicalDestDir); + if (relativeDestDir.split(import_path6.default.sep).includes("..")) + throw new Error(`Out of bound path "${canonicalDestDir}" found while processing file ${entry.fileName}`); + await this.extractEntry(entry); + debug2("finished processing", entry.fileName); + this.zipfile.readEntry(); + } catch (err) { + this.canceled = true; + this.zipfile.close(); + reject(err); + } + }); + }); + } + async extractEntry(entry) { + if (this.canceled) { + debug2("skipping entry extraction", entry.fileName, { cancelled: this.canceled }); + return; + } + if (this.opts.onEntry) + this.opts.onEntry(entry, this.zipfile); + const dest = import_path6.default.join(this.opts.dir, entry.fileName); + const mode = entry.externalFileAttributes >> 16 & 65535; + const IFMT = 61440; + const IFDIR = 16384; + const IFLNK = 40960; + const symlink = (mode & IFMT) === IFLNK; + let isDir = (mode & IFMT) === IFDIR; + if (!isDir && entry.fileName.endsWith("/")) + isDir = true; + const madeBy = entry.versionMadeBy >> 8; + if (!isDir) + isDir = madeBy === 0 && entry.externalFileAttributes === 16; + debug2("extracting entry", { filename: entry.fileName, isDir, isSymlink: symlink }); + const procMode = this.getExtractedMode(mode, isDir) & 511; + const destDir = isDir ? dest : import_path6.default.dirname(dest); + const mkdirOptions = { recursive: true }; + if (isDir) + mkdirOptions.mode = procMode; + debug2("mkdir", { dir: destDir, ...mkdirOptions }); + await import_fs9.promises.mkdir(destDir, mkdirOptions); + if (isDir) + return; + debug2("opening read stream", dest); + const readStream = await (0, import_util.promisify)(this.zipfile.openReadStream.bind(this.zipfile))(entry); + if (symlink) { + const link = await getStream(readStream); + debug2("creating symlink", link, dest); + await import_fs9.promises.symlink(link, dest); + } else { + await pipeline2(readStream, (0, import_fs9.createWriteStream)(dest, { mode: procMode })); + } + } + getExtractedMode(entryMode, isDir) { + let mode = entryMode; + if (mode === 0) { + if (isDir) { + if (this.opts.defaultDirMode) + mode = Number(this.opts.defaultDirMode); + if (!mode) + mode = 493; + } else { + if (this.opts.defaultFileMode) + mode = Number(this.opts.defaultFileMode); + if (!mode) + mode = 420; + } + } + return mode; + } + }; + } +}); + +// packages/utils/third_party/lockfile.ts +function probe(file, fs61, callback) { + const cachedPrecision = fs61[cacheSymbol]; + if (cachedPrecision) { + return fs61.stat(file, (err, stat) => { + if (err) + return callback(err); + callback(null, stat.mtime, cachedPrecision); + }); + } + const mtime = new Date(Math.ceil(Date.now() / 1e3) * 1e3 + 5); + fs61.utimes(file, mtime, mtime, (err) => { + if (err) + return callback(err); + fs61.stat(file, (err2, stat) => { + if (err2) + return callback(err2); + const precision = stat.mtime.getTime() % 1e3 === 0 ? "s" : "ms"; + Object.defineProperty(fs61, cacheSymbol, { value: precision }); + callback(null, stat.mtime, precision); + }); + }); +} +function getMtime(precision) { + let now = Date.now(); + if (precision === "s") + now = Math.ceil(now / 1e3) * 1e3; + return new Date(now); +} +function getLockFile(file, options) { + return options.lockfilePath || `${file}.lock`; +} +function resolveCanonicalPath(file, options, callback) { + if (!options.realpath) + return callback(null, import_path7.default.resolve(file)); + options.fs.realpath(file, callback); +} +function acquireLock(file, options, callback) { + const lockfilePath = getLockFile(file, options); + options.fs.mkdir(lockfilePath, (err) => { + if (!err) { + return probe(lockfilePath, options.fs, (err2, mtime, mtimePrecision) => { + if (err2) { + options.fs.rmdir(lockfilePath, () => { + }); + return callback(err2); + } + callback(null, mtime, mtimePrecision); + }); + } + if (err.code !== "EEXIST") + return callback(err); + if (options.stale <= 0) + return callback(Object.assign(new Error("Lock file is already being held"), { code: "ELOCKED", file })); + options.fs.stat(lockfilePath, (err2, stat) => { + if (err2) { + if (err2.code === "ENOENT") + return acquireLock(file, { ...options, stale: 0 }, callback); + return callback(err2); + } + if (!isLockStale(stat, options)) + return callback(Object.assign(new Error("Lock file is already being held"), { code: "ELOCKED", file })); + removeLock(file, options, (err3) => { + if (err3) + return callback(err3); + acquireLock(file, { ...options, stale: 0 }, callback); + }); + }); + }); +} +function isLockStale(stat, options) { + return stat.mtime.getTime() < Date.now() - options.stale; +} +function removeLock(file, options, callback) { + options.fs.rmdir(getLockFile(file, options), (err) => { + if (err && err.code !== "ENOENT") + return callback(err); + callback(null); + }); +} +function updateLock(file, options) { + const lock2 = locks[file]; + if (lock2.updateTimeout) + return; + lock2.updateDelay = lock2.updateDelay || options.update; + lock2.updateTimeout = setTimeout(() => { + lock2.updateTimeout = null; + options.fs.stat(lock2.lockfilePath, (err, stat) => { + const isOverThreshold = lock2.lastUpdate + options.stale < Date.now(); + if (err) { + if (err.code === "ENOENT" || isOverThreshold) + return setLockAsCompromised(file, lock2, Object.assign(err, { code: "ECOMPROMISED" })); + lock2.updateDelay = 1e3; + return updateLock(file, options); + } + const isMtimeOurs = lock2.mtime.getTime() === stat.mtime.getTime(); + if (!isMtimeOurs) { + return setLockAsCompromised( + file, + lock2, + Object.assign( + new Error("Unable to update lock within the stale threshold"), + { code: "ECOMPROMISED" } + ) + ); + } + const mtime = getMtime(lock2.mtimePrecision); + options.fs.utimes(lock2.lockfilePath, mtime, mtime, (err2) => { + const isOverThreshold2 = lock2.lastUpdate + options.stale < Date.now(); + if (lock2.released) + return; + if (err2) { + if (err2.code === "ENOENT" || isOverThreshold2) + return setLockAsCompromised(file, lock2, Object.assign(err2, { code: "ECOMPROMISED" })); + lock2.updateDelay = 1e3; + return updateLock(file, options); + } + lock2.mtime = mtime; + lock2.lastUpdate = Date.now(); + lock2.updateDelay = null; + updateLock(file, options); + }); + }); + }, lock2.updateDelay); + if (lock2.updateTimeout && lock2.updateTimeout.unref) + lock2.updateTimeout.unref(); +} +function setLockAsCompromised(file, lock2, err) { + lock2.released = true; + if (lock2.updateTimeout) + clearTimeout(lock2.updateTimeout); + if (locks[file] === lock2) + delete locks[file]; + lock2.options.onCompromised(err); +} +function lockImpl(file, options, callback) { + const resolvedOptions = { + stale: 1e4, + update: null, + realpath: true, + retries: 0, + fs: gracefulFs, + onCompromised: (err) => { + throw err; + }, + ...options + }; + resolvedOptions.retries = resolvedOptions.retries || 0; + resolvedOptions.retries = typeof resolvedOptions.retries === "number" ? { retries: resolvedOptions.retries } : resolvedOptions.retries; + resolvedOptions.stale = Math.max(resolvedOptions.stale || 0, 2e3); + resolvedOptions.update = resolvedOptions.update === null || resolvedOptions.update === void 0 ? resolvedOptions.stale / 2 : resolvedOptions.update || 0; + resolvedOptions.update = Math.max(Math.min(resolvedOptions.update, resolvedOptions.stale / 2), 1e3); + resolveCanonicalPath(file, resolvedOptions, (err, resolvedFile) => { + if (err) + return callback(err); + const canonicalFile = resolvedFile; + const operation = retry.operation(resolvedOptions.retries); + operation.attempt(() => { + acquireLock(canonicalFile, resolvedOptions, (err2, mtime, mtimePrecision) => { + if (operation.retry(err2 || void 0)) + return; + if (err2) + return callback(operation.mainError()); + const lock2 = locks[canonicalFile] = { + lockfilePath: getLockFile(canonicalFile, resolvedOptions), + mtime, + mtimePrecision, + options: resolvedOptions, + lastUpdate: Date.now() + }; + updateLock(canonicalFile, resolvedOptions); + callback(null, (releasedCallback) => { + if (lock2.released) { + return releasedCallback && releasedCallback(Object.assign(new Error("Lock is already released"), { code: "ERELEASED" })); + } + unlock(canonicalFile, { ...resolvedOptions, realpath: false }, releasedCallback || (() => { + })); + }); + }); + }); + }); +} +function unlock(file, options, callback) { + const resolvedOptions = { + stale: 1e4, + update: null, + realpath: true, + retries: 0, + fs: gracefulFs, + onCompromised: (err) => { + throw err; + }, + ...options + }; + resolveCanonicalPath(file, resolvedOptions, (err, resolvedFile) => { + if (err) + return callback(err); + const canonicalFile = resolvedFile; + const lock2 = locks[canonicalFile]; + if (!lock2) + return callback(Object.assign(new Error("Lock is not acquired/owned by you"), { code: "ENOTACQUIRED" })); + if (lock2.updateTimeout) + clearTimeout(lock2.updateTimeout); + lock2.released = true; + delete locks[canonicalFile]; + removeLock(canonicalFile, resolvedOptions, callback); + }); +} +function toPromise(method) { + return (...args) => new Promise((resolve, reject) => { + args.push((err, result2) => { + if (err) + reject(err); + else + resolve(result2); + }); + method(...args); + }); +} +function ensureCleanup() { + if (cleanupInitialized) + return; + cleanupInitialized = true; + onExit(() => { + for (const file in locks) { + const options = locks[file].options; + try { + options.fs.rmdirSync(getLockFile(file, options)); + } catch (e) { + } + } + }); +} +async function lock(file, options) { + ensureCleanup(); + const release = await toPromise(lockImpl)(file, options || {}); + return toPromise(release); +} +var import_path7, gracefulFs, retry, onExit, locks, cacheSymbol, cleanupInitialized; +var init_lockfile = __esm({ + "packages/utils/third_party/lockfile.ts"() { + "use strict"; + import_path7 = __toESM(require("path")); + gracefulFs = require("./utilsBundle").gracefulFs; + retry = require("./utilsBundle").retry; + onExit = require("./utilsBundle").onExit; + locks = {}; + cacheSymbol = Symbol(); + cleanupInitialized = false; + } +}); + +// packages/utils/index.ts +var utils_exports = {}; +__export(utils_exports, { + FastStats: () => FastStats, + HttpServer: () => HttpServer, + ImageChannel: () => ImageChannel, + NET_DEFAULT_TIMEOUT: () => NET_DEFAULT_TIMEOUT, + RecentLogsCollector: () => RecentLogsCollector, + SerializedFS: () => SerializedFS, + SocksProxy: () => SocksProxy, + SocksProxyHandler: () => SocksProxyHandler, + WSServer: () => WSServer, + ZipFile: () => ZipFile, + Zone: () => Zone, + addSuffixToFilePath: () => addSuffixToFilePath, + blendWithWhite: () => blendWithWhite, + calculateSha1: () => calculateSha1, + canAccessFile: () => canAccessFile, + colorDeltaE94: () => colorDeltaE94, + compare: () => compare, + compareBuffersOrStrings: () => compareBuffersOrStrings, + computeAllowedHosts: () => computeAllowedHosts, + copyFileAndMakeWritable: () => copyFileAndMakeWritable, + createGuid: () => createGuid, + createHttp2Server: () => createHttp2Server, + createHttpServer: () => createHttpServer, + createHttpsServer: () => createHttpsServer, + createProxyAgent: () => createProxyAgent, + currentZone: () => currentZone, + debugLogger: () => debugLogger, + debugMode: () => debugMode, + decorateServer: () => decorateServer, + defaultUserDataDirForChannel: () => defaultUserDataDirForChannel, + emptyZone: () => emptyZone, + envArrayToObject: () => envArrayToObject, + eventsHelper: () => eventsHelper, + existsAsync: () => existsAsync, + extractZip: () => extractZip, + fitToWidth: () => fitToWidth, + generateSelfSignedCertificate: () => generateSelfSignedCertificate, + getAsBooleanFromENV: () => getAsBooleanFromENV, + getComparator: () => getComparator, + getFromENV: () => getFromENV, + getPackageManager: () => getPackageManager, + getPackageManagerExecCommand: () => getPackageManagerExecCommand, + gracefullyCloseAll: () => gracefullyCloseAll, + gracefullyCloseSet: () => gracefullyCloseSet, + gracefullyProcessExitDoNotHang: () => gracefullyProcessExitDoNotHang, + guessClientName: () => guessClientName, + hostPlatform: () => hostPlatform, + hostnameFromHostHeader: () => hostnameFromHostHeader, + httpRequest: () => httpRequest, + isChromiumChannelName: () => isChromiumChannelName, + isCodingAgent: () => isCodingAgent, + isLikelyNpxGlobal: () => isLikelyNpxGlobal, + isOfficiallySupportedPlatform: () => isOfficiallySupportedPlatform, + isPathInside: () => isPathInside, + isSystemDirectory: () => isSystemDirectory, + isURLAvailable: () => isURLAvailable, + isUnderTest: () => isUnderTest, + isWritable: () => isWritable, + jsonStringifyForceASCII: () => jsonStringifyForceASCII, + launchProcess: () => launchProcess, + lock: () => lock, + makeSocketPath: () => makeSocketPath, + makeWaitForNextTask: () => makeWaitForNextTask, + mkdirIfNeeded: () => mkdirIfNeeded, + nodePlatform: () => nodePlatform, + parsePattern: () => parsePattern, + perMessageDeflate: () => perMessageDeflate, + removeFolders: () => removeFolders, + resolveWithinRoot: () => resolveWithinRoot, + rgb2gray: () => rgb2gray, + sanitizeForFilePath: () => sanitizeForFilePath, + serveFolder: () => serveFolder, + setBoxedStackPrefixes: () => setBoxedStackPrefixes, + setPlaywrightTestProcessEnv: () => setPlaywrightTestProcessEnv, + shortPlatform: () => shortPlatform, + spawnAsync: () => spawnAsync, + srgb2xyz: () => srgb2xyz, + ssim: () => ssim, + startHttpServer: () => startHttpServer, + startProfiling: () => startProfiling, + stopProfiling: () => stopProfiling, + stringWidth: () => stringWidth, + throwingResolveWithinRoot: () => throwingResolveWithinRoot, + toPosixPath: () => toPosixPath, + trimLongString: () => trimLongString, + urlHostFromAddress: () => urlHostFromAddress, + wrapInASCIIBox: () => wrapInASCIIBox, + xyz2lab: () => xyz2lab +}); +var init_utils = __esm({ + "packages/utils/index.ts"() { + "use strict"; + init_ascii(); + init_chromiumChannels(); + init_comparators(); + init_crypto(); + init_debug(); + init_debugLogger(); + init_env(); + init_eventsHelper(); + init_fileUtils(); + init_hostPlatform(); + init_httpServer(); + init_network(); + init_nodePlatform(); + init_processLauncher(); + init_profiler(); + init_serializedFS(); + init_socksProxy(); + init_spawnAsync(); + init_stringWidth(); + init_task(); + init_wsServer(); + init_zipFile(); + init_zones(); + init_extractZip(); + init_lockfile(); + init_colorUtils(); + init_compare(); + init_imageChannel(); + init_stats(); + } +}); + +// packages/playwright-core/src/client/eventEmitter.ts +function checkListener(listener) { + if (typeof listener !== "function") + throw new TypeError('The "listener" argument must be of type Function. Received type ' + typeof listener); +} +function unwrapListener(l) { + return wrappedListener(l) ?? l; +} +function unwrapListeners(arr) { + return arr.map((l) => wrappedListener(l) ?? l); +} +function wrappedListener(l) { + return l.listener; +} +var EventEmitter3, OnceWrapper; +var init_eventEmitter = __esm({ + "packages/playwright-core/src/client/eventEmitter.ts"() { + "use strict"; + EventEmitter3 = class { + constructor(platform) { + this._events = void 0; + this._eventsCount = 0; + this._maxListeners = void 0; + this._pendingHandlers = /* @__PURE__ */ new Map(); + this._platform = platform; + if (this._events === void 0 || this._events === Object.getPrototypeOf(this)._events) { + this._events = /* @__PURE__ */ Object.create(null); + this._eventsCount = 0; + } + this._maxListeners = this._maxListeners || void 0; + this.on = this.addListener; + this.off = this.removeListener; + } + setMaxListeners(n) { + if (typeof n !== "number" || n < 0 || Number.isNaN(n)) + throw new RangeError('The value of "n" is out of range. It must be a non-negative number. Received ' + n + "."); + this._maxListeners = n; + return this; + } + getMaxListeners() { + return this._maxListeners === void 0 ? this._platform.defaultMaxListeners() : this._maxListeners; + } + emit(type3, ...args) { + const events = this._events; + if (events === void 0) + return false; + const handler = events?.[type3]; + if (handler === void 0) + return false; + if (typeof handler === "function") { + this._callHandler(type3, handler, args); + } else { + const len = handler.length; + const listeners = handler.slice(); + for (let i = 0; i < len; ++i) + this._callHandler(type3, listeners[i], args); + } + return true; + } + _callHandler(type3, handler, args) { + const promise = Reflect.apply(handler, this, args); + if (!(promise instanceof Promise)) + return; + let set = this._pendingHandlers.get(type3); + if (!set) { + set = /* @__PURE__ */ new Set(); + this._pendingHandlers.set(type3, set); + } + set.add(promise); + promise.catch((e) => { + if (this._rejectionHandler) + this._rejectionHandler(e); + else + throw e; + }).finally(() => set.delete(promise)); + } + addListener(type3, listener) { + return this._addListener(type3, listener, false); + } + on(type3, listener) { + return this._addListener(type3, listener, false); + } + _addListener(type3, listener, prepend) { + checkListener(listener); + let events = this._events; + let existing; + if (events === void 0) { + events = this._events = /* @__PURE__ */ Object.create(null); + this._eventsCount = 0; + } else { + if (events.newListener !== void 0) { + this.emit("newListener", type3, unwrapListener(listener)); + events = this._events; + } + existing = events[type3]; + } + if (existing === void 0) { + existing = events[type3] = listener; + ++this._eventsCount; + } else { + if (typeof existing === "function") { + existing = events[type3] = prepend ? [listener, existing] : [existing, listener]; + } else if (prepend) { + existing.unshift(listener); + } else { + existing.push(listener); + } + const m = this.getMaxListeners(); + if (m > 0 && existing.length > m && !existing.warned) { + existing.warned = true; + const w = new Error("Possible EventEmitter memory leak detected. " + existing.length + " " + String(type3) + " listeners added. Use emitter.setMaxListeners() to increase limit"); + w.name = "MaxListenersExceededWarning"; + w.emitter = this; + w.type = type3; + w.count = existing.length; + if (!this._platform.isUnderTest()) { + console.warn(w); + } + } + } + return this; + } + prependListener(type3, listener) { + return this._addListener(type3, listener, true); + } + once(type3, listener) { + checkListener(listener); + this.on(type3, new OnceWrapper(this, type3, listener).wrapperFunction); + return this; + } + prependOnceListener(type3, listener) { + checkListener(listener); + this.prependListener(type3, new OnceWrapper(this, type3, listener).wrapperFunction); + return this; + } + removeListener(type3, listener) { + checkListener(listener); + const events = this._events; + if (events === void 0) + return this; + const list = events[type3]; + if (list === void 0) + return this; + if (list === listener || list.listener === listener) { + if (--this._eventsCount === 0) { + this._events = /* @__PURE__ */ Object.create(null); + } else { + delete events[type3]; + if (events.removeListener) + this.emit("removeListener", type3, list.listener ?? listener); + } + } else if (typeof list !== "function") { + let position = -1; + let originalListener; + for (let i = list.length - 1; i >= 0; i--) { + if (list[i] === listener || wrappedListener(list[i]) === listener) { + originalListener = wrappedListener(list[i]); + position = i; + break; + } + } + if (position < 0) + return this; + if (position === 0) + list.shift(); + else + list.splice(position, 1); + if (list.length === 1) + events[type3] = list[0]; + if (events.removeListener !== void 0) + this.emit("removeListener", type3, originalListener || listener); + } + return this; + } + off(type3, listener) { + return this.removeListener(type3, listener); + } + removeAllListeners(type3, options) { + this._removeAllListeners(type3); + if (!options) + return this; + if (options.behavior === "wait") { + const errors = []; + this._rejectionHandler = (error) => errors.push(error); + return this._waitFor(type3).then(() => { + if (errors.length) + throw errors[0]; + }); + } + if (options.behavior === "ignoreErrors") + this._rejectionHandler = () => { + }; + return Promise.resolve(); + } + _removeAllListeners(type3) { + const events = this._events; + if (!events) + return; + if (!events.removeListener) { + if (type3 === void 0) { + this._events = /* @__PURE__ */ Object.create(null); + this._eventsCount = 0; + } else if (events[type3] !== void 0) { + if (--this._eventsCount === 0) + this._events = /* @__PURE__ */ Object.create(null); + else + delete events[type3]; + } + return; + } + if (type3 === void 0) { + const keys = Object.keys(events); + let key; + for (let i = 0; i < keys.length; ++i) { + key = keys[i]; + if (key === "removeListener") + continue; + this._removeAllListeners(key); + } + this._removeAllListeners("removeListener"); + this._events = /* @__PURE__ */ Object.create(null); + this._eventsCount = 0; + return; + } + const listeners = events[type3]; + if (typeof listeners === "function") { + this.removeListener(type3, listeners); + } else if (listeners !== void 0) { + for (let i = listeners.length - 1; i >= 0; i--) + this.removeListener(type3, listeners[i]); + } + } + listeners(type3) { + return this._listeners(this, type3, true); + } + rawListeners(type3) { + return this._listeners(this, type3, false); + } + listenerCount(type3) { + const events = this._events; + if (events !== void 0) { + const listener = events[type3]; + if (typeof listener === "function") + return 1; + if (listener !== void 0) + return listener.length; + } + return 0; + } + eventNames() { + return this._eventsCount > 0 && this._events ? Reflect.ownKeys(this._events) : []; + } + async _waitFor(type3) { + let promises = []; + if (type3) { + promises = [...this._pendingHandlers.get(type3) || []]; + } else { + promises = []; + for (const [, pending] of this._pendingHandlers) + promises.push(...pending); + } + await Promise.all(promises); + } + _listeners(target, type3, unwrap) { + const events = target._events; + if (events === void 0) + return []; + const listener = events[type3]; + if (listener === void 0) + return []; + if (typeof listener === "function") + return unwrap ? [unwrapListener(listener)] : [listener]; + return unwrap ? unwrapListeners(listener) : listener.slice(); + } + }; + OnceWrapper = class { + constructor(eventEmitter, eventType, listener) { + this._fired = false; + this._eventEmitter = eventEmitter; + this._eventType = eventType; + this._listener = listener; + this.wrapperFunction = this._handle.bind(this); + this.wrapperFunction.listener = listener; + } + _handle(...args) { + if (this._fired) + return; + this._fired = true; + this._eventEmitter.removeListener(this._eventType, this.wrapperFunction); + return this._listener.apply(this._eventEmitter, args); + } + }; + } +}); + +// packages/playwright-core/src/bootstrap.ts +var minimumMajorNodeVersion, currentNodeVersion, major; +var init_bootstrap = __esm({ + "packages/playwright-core/src/bootstrap.ts"() { + "use strict"; + minimumMajorNodeVersion = 18; + currentNodeVersion = process.versions.node; + major = +currentNodeVersion.split(".")[0]; + if (major < minimumMajorNodeVersion) { + console.error( + "You are running Node.js " + currentNodeVersion + `. +Playwright requires Node.js ${minimumMajorNodeVersion} or higher. +Please update your version of Node.js.` + ); + process.exit(1); + } + if (process.env.PW_INSTRUMENT_MODULES) { + const Module = require("module"); + const originalLoad = Module._load; + const root = { name: "", selfMs: 0, totalMs: 0, childrenMs: 0, children: [] }; + let current = root; + const stack = []; + Module._load = function(request2, _parent, _isMain) { + const node = { name: request2, selfMs: 0, totalMs: 0, childrenMs: 0, children: [] }; + current.children.push(node); + stack.push(current); + current = node; + const start3 = performance.now(); + let result2; + try { + result2 = originalLoad.apply(this, arguments); + } catch (e) { + current = stack.pop(); + current.children.pop(); + throw e; + } + const duration = performance.now() - start3; + node.totalMs = duration; + node.selfMs = Math.max(0, duration - node.childrenMs); + current = stack.pop(); + current.childrenMs += duration; + return result2; + }; + process.on("exit", () => { + function printTree(node, prefix, isLast, lines2, depth) { + if (node.totalMs < 1 && depth > 0) + return; + const connector = depth === 0 ? "" : isLast ? "\u2514\u2500\u2500 " : "\u251C\u2500\u2500 "; + const time = `${node.totalMs.toFixed(1).padStart(8)}ms`; + const self2 = node.children.length ? ` (self: ${node.selfMs.toFixed(1)}ms)` : ""; + lines2.push(`${time} ${prefix}${connector}${node.name}${self2}`); + const childPrefix = prefix + (depth === 0 ? "" : isLast ? " " : "\u2502 "); + const sorted2 = node.children.slice().sort((a, b) => b.totalMs - a.totalMs); + for (let i = 0; i < sorted2.length; i++) + printTree(sorted2[i], childPrefix, i === sorted2.length - 1, lines2, depth + 1); + } + let totalModules = 0; + function count(n) { + totalModules++; + n.children.forEach(count); + } + root.children.forEach(count); + const lines = []; + const sorted = root.children.slice().sort((a, b) => b.totalMs - a.totalMs); + for (let i = 0; i < sorted.length; i++) + printTree(sorted[i], "", i === sorted.length - 1, lines, 0); + const totalMs = root.children.reduce((s, c) => s + c.totalMs, 0); + process.stderr.write(` +--- Module load tree: ${totalModules} modules, ${totalMs.toFixed(0)}ms total --- +` + lines.join("\n") + "\n"); + const flat = /* @__PURE__ */ new Map(); + function gather(n) { + const existing = flat.get(n.name); + if (existing) { + existing.selfMs += n.selfMs; + existing.totalMs += n.totalMs; + existing.count++; + } else { + flat.set(n.name, { selfMs: n.selfMs, totalMs: n.totalMs, count: 1 }); + } + n.children.forEach(gather); + } + root.children.forEach(gather); + const top50 = [...flat.entries()].sort((a, b) => b[1].selfMs - a[1].selfMs).slice(0, 50); + const flatLines = top50.map( + ([mod, { selfMs, totalMs: totalMs2, count: count2 }]) => `${selfMs.toFixed(1).padStart(8)}ms self ${totalMs2.toFixed(1).padStart(8)}ms total (x${String(count2).padStart(3)}) ${mod}` + ); + process.stderr.write(` +--- Top 50 modules by self time --- +` + flatLines.join("\n") + "\n"); + }); + } + } +}); + +// packages/playwright-core/src/package.ts +function libPath(...parts) { + return import_path8.default.join(packageRoot, "lib", ...parts); +} +var import_path8, packageRoot, packageJSON, binPath; +var init_package = __esm({ + "packages/playwright-core/src/package.ts"() { + "use strict"; + import_path8 = __toESM(require("path")); + packageRoot = import_path8.default.join(__dirname, ".."); + packageJSON = require(import_path8.default.join(packageRoot, "package.json")); + binPath = import_path8.default.join(packageRoot, "bin"); + } +}); + +// packages/playwright-core/src/tools/trace/traceParser.ts +async function extractTrace(traceFile, outDir) { + const zipFile = new ZipFile(traceFile); + try { + const entries = await zipFile.entries(); + for (const entry of entries) { + const outPath = resolveWithinRoot(outDir, entry); + if (!outPath) + throw new Error(`Trace entry '${entry}' escapes output directory`); + await import_fs10.default.promises.mkdir(import_path9.default.dirname(outPath), { recursive: true }); + const buffer = await zipFile.read(entry); + await import_fs10.default.promises.writeFile(outPath, buffer); + } + } finally { + zipFile.close(); + } +} +var import_fs10, import_path9, DirTraceLoaderBackend; +var init_traceParser = __esm({ + "packages/playwright-core/src/tools/trace/traceParser.ts"() { + "use strict"; + import_fs10 = __toESM(require("fs")); + import_path9 = __toESM(require("path")); + init_fileUtils(); + init_zipFile(); + DirTraceLoaderBackend = class { + constructor(dir) { + this._dir = dir; + } + isLive() { + return false; + } + async entryNames() { + const entries = []; + const walk = async (dir, prefix) => { + const items = await import_fs10.default.promises.readdir(dir, { withFileTypes: true }); + for (const item of items) { + if (item.isDirectory()) + await walk(import_path9.default.join(dir, item.name), prefix ? `${prefix}/${item.name}` : item.name); + else + entries.push(prefix ? `${prefix}/${item.name}` : item.name); + } + }; + await walk(this._dir, ""); + return entries; + } + async hasEntry(entryName) { + const resolved = resolveWithinRoot(this._dir, entryName); + if (!resolved) + return false; + try { + await import_fs10.default.promises.access(resolved); + return true; + } catch { + return false; + } + } + async readText(entryName) { + const resolved = resolveWithinRoot(this._dir, entryName); + if (!resolved) + return; + try { + return await import_fs10.default.promises.readFile(resolved, "utf-8"); + } catch { + } + } + async readBlob(entryName) { + const resolved = resolveWithinRoot(this._dir, entryName); + if (!resolved) + return; + try { + const buffer = await import_fs10.default.promises.readFile(resolved); + return new Blob([new Uint8Array(buffer)]); + } catch { + } + } + }; + } +}); + +// packages/playwright-core/src/tools/trace/traceUtils.ts +function ensureTraceOpen() { + if (!import_fs11.default.existsSync(traceDir)) + throw new Error(`No trace opened. Run 'npx playwright trace open ' first.`); + return traceDir; +} +async function closeTrace() { + if (import_fs11.default.existsSync(traceDir)) + await import_fs11.default.promises.rm(traceDir, { recursive: true }); +} +async function openTrace(traceFile) { + const filePath = import_path10.default.resolve(traceFile); + if (!import_fs11.default.existsSync(filePath)) + throw new Error(`Trace file not found: ${filePath}`); + await closeTrace(); + await import_fs11.default.promises.mkdir(traceDir, { recursive: true }); + if (filePath.endsWith(".zip")) + await extractTrace(filePath, traceDir); + else + await import_fs11.default.promises.writeFile(import_path10.default.join(traceDir, ".link"), filePath, "utf-8"); +} +async function loadTrace() { + const dir = ensureTraceOpen(); + const linkFile = import_path10.default.join(dir, ".link"); + let traceDir2; + let traceFile; + if (import_fs11.default.existsSync(linkFile)) { + const tracePath = await import_fs11.default.promises.readFile(linkFile, "utf-8"); + traceDir2 = import_path10.default.dirname(tracePath); + traceFile = import_path10.default.basename(tracePath); + } else { + traceDir2 = dir; + } + const backend = new DirTraceLoaderBackend(traceDir2); + const loader = new TraceLoader(); + await loader.load(backend, traceFile); + const model = new TraceModel(traceDir2, loader.contextEntries); + return new LoadedTrace(model, loader, buildOrdinalMap(model)); +} +function formatTimestamp(ms, base) { + const relative = ms - base; + if (relative < 0) + return "0:00.000"; + const totalMs = Math.floor(relative); + const minutes = Math.floor(totalMs / 6e4); + const seconds = Math.floor(totalMs % 6e4 / 1e3); + const millis = totalMs % 1e3; + return `${minutes}:${seconds.toString().padStart(2, "0")}.${millis.toString().padStart(3, "0")}`; +} +function actionTitle(action) { + return renderTitleForCall({ ...action, type: action.class }) || `${action.class}.${action.method}`; +} +async function saveOutputFile(fileName, content, explicitOutput) { + let outFile; + if (explicitOutput) { + outFile = explicitOutput; + } else { + const resolved = resolveWithinRoot(cliOutputDir, fileName); + if (!resolved) + throw new Error(`Attachment name '${fileName}' escapes output directory`); + await import_fs11.default.promises.mkdir(import_path10.default.dirname(resolved), { recursive: true }); + outFile = resolved; + } + await import_fs11.default.promises.writeFile(outFile, content); + return outFile; +} +function buildOrdinalMap(model) { + const actions = model.actions.filter((a) => a.group !== "configuration"); + const { rootItem } = buildActionTree(actions); + const ordinalToCallId = /* @__PURE__ */ new Map(); + const callIdToOrdinal = /* @__PURE__ */ new Map(); + let ordinal = 1; + const visit = (item) => { + ordinalToCallId.set(ordinal, item.action.callId); + callIdToOrdinal.set(item.action.callId, ordinal); + ordinal++; + for (const child of item.children) + visit(child); + }; + for (const child of rootItem.children) + visit(child); + return { ordinalToCallId, callIdToOrdinal }; +} +var import_fs11, import_path10, traceDir, cliOutputDir, LoadedTrace; +var init_traceUtils2 = __esm({ + "packages/playwright-core/src/tools/trace/traceUtils.ts"() { + "use strict"; + import_fs11 = __toESM(require("fs")); + import_path10 = __toESM(require("path")); + init_traceModel(); + init_traceLoader(); + init_protocolFormatter(); + init_fileUtils(); + init_traceParser(); + traceDir = import_path10.default.join(".playwright-cli", "trace"); + cliOutputDir = ".playwright-cli"; + LoadedTrace = class { + constructor(model, loader, ordinals) { + this.model = model; + this.loader = loader; + this.ordinalToCallId = ordinals.ordinalToCallId; + this.callIdToOrdinal = ordinals.callIdToOrdinal; + } + resolveActionId(actionId) { + const ordinal = parseInt(actionId, 10); + if (!isNaN(ordinal)) { + const callId = this.ordinalToCallId.get(ordinal); + if (callId) + return this.model.actions.find((a) => a.callId === callId); + } + return this.model.actions.find((a) => a.callId === actionId); + } + }; + } +}); + +// packages/playwright-core/src/tools/trace/traceOpen.ts +async function traceOpen(traceFile) { + await openTrace(traceFile); + await traceInfo(); +} +async function traceInfo() { + const trace = await loadTrace(); + const model = trace.model; + const info = { + browser: model.browserName || "unknown", + platform: model.platform || "unknown", + playwrightVersion: model.playwrightVersion || "unknown", + title: model.title || "", + duration: msToString(model.endTime - model.startTime), + durationMs: model.endTime - model.startTime, + startTime: model.wallTime ? new Date(model.wallTime).toISOString() : "unknown", + viewport: model.options.viewport ? `${model.options.viewport.width}x${model.options.viewport.height}` : "default", + actions: model.actions.length, + pages: model.pages.length, + network: model.resources.length, + errors: model.errorDescriptors.length, + attachments: model.attachments.length, + consoleMessages: model.events.filter((e) => e.type === "console").length + }; + console.log(""); + console.log(` Browser: ${info.browser}`); + console.log(` Platform: ${info.platform}`); + console.log(` Playwright: ${info.playwrightVersion}`); + if (info.title) + console.log(` Title: ${info.title}`); + console.log(` Duration: ${info.duration}`); + console.log(` Start time: ${info.startTime}`); + console.log(` Viewport: ${info.viewport}`); + console.log(` Actions: ${info.actions}`); + console.log(` Pages: ${info.pages}`); + console.log(` Network: ${info.network} requests`); + console.log(` Errors: ${info.errors}`); + console.log(` Attachments: ${info.attachments}`); + console.log(` Console: ${info.consoleMessages} messages`); + console.log(""); +} +var init_traceOpen = __esm({ + "packages/playwright-core/src/tools/trace/traceOpen.ts"() { + "use strict"; + init_formatUtils(); + init_traceUtils2(); + } +}); + +// packages/playwright-core/src/tools/trace/traceActions.ts +async function traceActions(options) { + const trace = await loadTrace(); + const actions = filterActions(trace.model.actions, options); + const { rootItem } = buildActionTree(actions); + console.log(` ${"#".padStart(4)} ${"Time".padEnd(9)} ${"Action".padEnd(55)} ${"Duration".padStart(8)}`); + console.log(` ${"\u2500".repeat(4)} ${"\u2500".repeat(9)} ${"\u2500".repeat(55)} ${"\u2500".repeat(8)}`); + const visit = (item, indent) => { + const action = item.action; + const ordinal = trace.callIdToOrdinal.get(action.callId) ?? "?"; + const ts = formatTimestamp(action.startTime, trace.model.startTime); + const duration = action.endTime ? msToString(action.endTime - action.startTime) : "running"; + const title = actionTitle(action); + const locator2 = actionLocator(action); + const error = action.error ? " \u2717" : ""; + const prefix = ` ${(ordinal + ".").padStart(4)} ${ts} ${indent}`; + console.log(`${prefix}${title.padEnd(Math.max(1, 55 - indent.length))} ${duration.padStart(8)}${error}`); + if (locator2) + console.log(`${" ".repeat(prefix.length)}${locator2}`); + for (const child of item.children) + visit(child, indent + " "); + }; + for (const child of rootItem.children) + visit(child, ""); +} +function filterActions(actions, options) { + let result2 = actions.filter((a) => a.group !== "configuration"); + if (options.grep) { + const pattern = new RegExp(options.grep, "i"); + result2 = result2.filter((a) => pattern.test(actionTitle(a)) || pattern.test(actionLocator(a) || "")); + } + if (options.errorsOnly) + result2 = result2.filter((a) => !!a.error); + return result2; +} +function actionLocator(action, sdkLanguage) { + return action.params.selector ? asLocatorDescription(sdkLanguage || "javascript", action.params.selector) : void 0; +} +async function traceAction(actionId) { + const trace = await loadTrace(); + const action = trace.resolveActionId(actionId); + if (!action) { + console.error(`Action '${actionId}' not found. Use 'trace actions' to see available action IDs.`); + process.exitCode = 1; + return; + } + const title = actionTitle(action); + console.log(` + ${title} +`); + console.log(" Time"); + console.log(` start: ${formatTimestamp(action.startTime, trace.model.startTime)}`); + const duration = action.endTime ? msToString(action.endTime - action.startTime) : action.error ? "Timed Out" : "Running"; + console.log(` duration: ${duration}`); + const paramKeys = Object.keys(action.params).filter((name) => name !== "info"); + if (paramKeys.length) { + console.log("\n Parameters"); + for (const key of paramKeys) { + const value2 = formatParamValue(action.params[key]); + console.log(` ${key}: ${value2}`); + } + } + if (action.result) { + console.log("\n Return value"); + for (const [key, value2] of Object.entries(action.result)) + console.log(` ${key}: ${formatParamValue(value2)}`); + } + if (action.error) { + console.log("\n Error"); + console.log(` ${action.error.message}`); + } + if (action.log.length) { + console.log("\n Log"); + for (const entry of action.log) { + const time = entry.time !== -1 ? formatTimestamp(entry.time, trace.model.startTime) : ""; + console.log(` ${time.padEnd(12)} ${entry.message}`); + } + } + if (action.stack?.length) { + console.log("\n Source"); + for (const frame of action.stack.slice(0, 5)) { + const file = frame.file.replace(/.*[/\\](.*)/, "$1"); + console.log(` ${file}:${frame.line}:${frame.column}`); + } + } + const snapshots = []; + if (action.beforeSnapshot) + snapshots.push("before"); + if (action.inputSnapshot) + snapshots.push("input"); + if (action.afterSnapshot) + snapshots.push("after"); + if (snapshots.length) { + console.log("\n Snapshots"); + console.log(` available: ${snapshots.join(", ")}`); + console.log(` usage: npx playwright trace snapshot ${actionId} --name <${snapshots.join("|")}>`); + } + console.log(""); +} +function formatParamValue(value2) { + if (value2 === void 0 || value2 === null) + return String(value2); + if (typeof value2 === "string") + return `"${value2}"`; + if (typeof value2 !== "object") + return String(value2); + if (value2.guid) + return ""; + return JSON.stringify(value2).slice(0, 1e3); +} +var init_traceActions = __esm({ + "packages/playwright-core/src/tools/trace/traceActions.ts"() { + "use strict"; + init_traceModel(); + init_locatorGenerators(); + init_formatUtils(); + init_traceUtils2(); + } +}); + +// packages/playwright-core/src/tools/trace/traceRequests.ts +async function traceRequests(options) { + const trace = await loadTrace(); + const model = trace.model; + let indexed = model.resources.map((r, i) => ({ resource: r, ordinal: i + 1 })); + if (options.grep) { + const pattern = new RegExp(options.grep, "i"); + indexed = indexed.filter(({ resource: r }) => pattern.test(r.request.url)); + } + if (options.method) + indexed = indexed.filter(({ resource: r }) => r.request.method.toLowerCase() === options.method.toLowerCase()); + if (options.status) { + const code = parseInt(options.status, 10); + indexed = indexed.filter(({ resource: r }) => r.response.status === code); + } + if (options.failed) + indexed = indexed.filter(({ resource: r }) => r.response.status >= 400 || r.response.status === -1); + if (!indexed.length) { + console.log(" No network requests"); + return; + } + console.log(` ${"#".padStart(4)} ${"Method".padEnd(8)} ${"Status".padEnd(8)} ${"Name".padEnd(45)} ${"Duration".padStart(10)} ${"Size".padStart(8)} ${"Route".padEnd(10)}`); + console.log(` ${"\u2500".repeat(4)} ${"\u2500".repeat(8)} ${"\u2500".repeat(8)} ${"\u2500".repeat(45)} ${"\u2500".repeat(10)} ${"\u2500".repeat(8)} ${"\u2500".repeat(10)}`); + for (const { resource: r, ordinal } of indexed) { + let name; + try { + const url2 = new URL(r.request.url); + name = url2.pathname.substring(url2.pathname.lastIndexOf("/") + 1); + if (!name) + name = url2.host; + if (url2.search) + name += url2.search; + } catch { + name = r.request.url; + } + if (name.length > 45) + name = name.substring(0, 42) + "..."; + const status = r.response.status > 0 ? String(r.response.status) : "ERR"; + const size = r.response._transferSize > 0 ? r.response._transferSize : r.response.bodySize; + const route2 = formatRouteStatus(r); + console.log(` ${(ordinal + ".").padStart(4)} ${r.request.method.padEnd(8)} ${status.padEnd(8)} ${name.padEnd(45)} ${msToString(r.time).padStart(10)} ${bytesToString2(size).padStart(8)} ${route2.padEnd(10)}`); + } +} +async function traceRequest(requestId) { + const trace = await loadTrace(); + const model = trace.model; + const ordinal = parseInt(requestId, 10); + const resource = !isNaN(ordinal) && ordinal >= 1 && ordinal <= model.resources.length ? model.resources[ordinal - 1] : void 0; + if (!resource) { + console.error(`Request '${requestId}' not found. Use 'trace requests' to see available request IDs.`); + process.exitCode = 1; + return; + } + const r = resource; + const status = r.response.status > 0 ? `${r.response.status} ${r.response.statusText}` : "ERR"; + const size = r.response._transferSize > 0 ? r.response._transferSize : r.response.bodySize; + console.log(` + ${r.request.method} ${r.request.url} +`); + console.log(" General"); + console.log(` status: ${status}`); + console.log(` duration: ${msToString(r.time)}`); + console.log(` size: ${bytesToString2(size)}`); + if (r.response.content.mimeType) + console.log(` type: ${r.response.content.mimeType}`); + const route2 = formatRouteStatus(r); + if (route2) + console.log(` route: ${route2}`); + if (r.serverIPAddress) + console.log(` server: ${r.serverIPAddress}${r._serverPort ? ":" + r._serverPort : ""}`); + if (r.response._failureText) + console.log(` error: ${r.response._failureText}`); + if (r.request.headers.length) { + console.log("\n Request headers"); + for (const h of r.request.headers) + console.log(` ${h.name}: ${h.value}`); + } + if (r.request.postData) { + console.log("\n Request body"); + const resource2 = r.request.postData._sha1 ?? r.request.postData._file; + if (resource2) { + console.log(` ${import_path11.default.relative(process.cwd(), import_path11.default.join(trace.model.traceUri, "resources", resource2))}`); + } else { + const text2 = r.request.postData.text.length > 2e3 ? r.request.postData.text.substring(0, 2e3) + "..." : r.request.postData.text; + console.log(` ${text2}`); + } + } + if (r.response.headers.length) { + console.log("\n Response headers"); + for (const h of r.response.headers) + console.log(` ${h.name}: ${h.value}`); + } + if (r.response.bodySize > 0) { + const resource2 = r.response.content._sha1 ?? r.response.content._file; + if (resource2) { + console.log("\n Response body"); + console.log(` ${import_path11.default.relative(process.cwd(), import_path11.default.join(trace.model.traceUri, "resources", resource2))}`); + } else if (r.response.content.text) { + const text2 = r.response.content.text.length > 2e3 ? r.response.content.text.substring(0, 2e3) + "..." : r.response.content.text; + console.log("\n Response body"); + console.log(` ${text2}`); + } + } + if (r._securityDetails) { + console.log("\n Security"); + if (r._securityDetails.protocol) + console.log(` protocol: ${r._securityDetails.protocol}`); + if (r._securityDetails.subjectName) + console.log(` subject: ${r._securityDetails.subjectName}`); + if (r._securityDetails.issuer) + console.log(` issuer: ${r._securityDetails.issuer}`); + } + console.log(""); +} +function bytesToString2(bytes) { + if (bytes < 0 || !isFinite(bytes)) + return "-"; + if (bytes === 0) + return "0"; + if (bytes < 1e3) + return bytes.toFixed(0); + const kb = bytes / 1024; + if (kb < 1e3) + return kb.toFixed(1) + "K"; + const mb = kb / 1024; + if (mb < 1e3) + return mb.toFixed(1) + "M"; + const gb = mb / 1024; + return gb.toFixed(1) + "G"; +} +function formatRouteStatus(r) { + if (r._wasAborted) + return "aborted"; + if (r._wasContinued) + return "continued"; + if (r._wasFulfilled) + return "fulfilled"; + if (r._apiRequest) + return "api"; + return ""; +} +var import_path11; +var init_traceRequests = __esm({ + "packages/playwright-core/src/tools/trace/traceRequests.ts"() { + "use strict"; + import_path11 = __toESM(require("path")); + init_formatUtils(); + init_traceUtils2(); + } +}); + +// packages/playwright-core/src/tools/trace/traceConsole.ts +async function traceConsole(options) { + const trace = await loadTrace(); + const model = trace.model; + const items = []; + for (const event of model.events) { + if (event.type === "console") { + if (options.stdio) + continue; + const level = event.messageType; + if (options.errorsOnly && level !== "error") + continue; + if (options.warnings && level !== "error" && level !== "warning") + continue; + const url2 = event.location.url; + const filename = url2 ? url2.substring(url2.lastIndexOf("/") + 1) : ""; + items.push({ + type: "browser", + level, + text: event.text, + location: `${filename}:${event.location.lineNumber}`, + timestamp: event.time + }); + } + if (event.type === "event" && event.method === "pageError") { + if (options.stdio) + continue; + const error = event.params.error; + items.push({ + type: "browser", + level: "error", + text: error?.error?.message || String(error?.value || ""), + timestamp: event.time + }); + } + } + for (const event of model.stdio) { + if (options.browser) + continue; + if (options.errorsOnly && event.type !== "stderr") + continue; + if (options.warnings && event.type !== "stderr") + continue; + let text2 = ""; + if (event.text) + text2 = event.text.trim(); + if (event.base64) + text2 = Buffer.from(event.base64, "base64").toString("utf-8").trim(); + if (!text2) + continue; + items.push({ + type: event.type, + level: event.type === "stderr" ? "error" : "info", + text: text2, + timestamp: event.timestamp + }); + } + items.sort((a, b) => a.timestamp - b.timestamp); + if (!items.length) { + console.log(" No console entries"); + return; + } + for (const item of items) { + const ts = formatTimestamp(item.timestamp, model.startTime); + const source11 = item.type === "browser" ? "[browser]" : `[${item.type}]`; + const level = item.level.padEnd(8); + const location2 = item.location ? ` ${item.location}` : ""; + console.log(` ${ts} ${source11.padEnd(10)} ${level} ${item.text}${location2}`); + } +} +var init_traceConsole = __esm({ + "packages/playwright-core/src/tools/trace/traceConsole.ts"() { + "use strict"; + init_traceUtils2(); + } +}); + +// packages/playwright-core/src/tools/trace/traceErrors.ts +async function traceErrors() { + const trace = await loadTrace(); + const model = trace.model; + if (!model.errorDescriptors.length) { + console.log(" No errors"); + return; + } + for (const error of model.errorDescriptors) { + if (error.action) { + const title = actionTitle(error.action); + console.log(` + \u2717 ${title}`); + } else { + console.log(` + \u2717 Error`); + } + if (error.stack?.length) { + const frame = error.stack[0]; + const file = frame.file.replace(/.*[/\\](.*)/, "$1"); + console.log(` at ${file}:${frame.line}:${frame.column}`); + } + console.log(""); + const indented = error.message.split("\n").map((l) => ` ${l}`).join("\n"); + console.log(indented); + } + console.log(""); +} +var init_traceErrors = __esm({ + "packages/playwright-core/src/tools/trace/traceErrors.ts"() { + "use strict"; + init_traceUtils2(); + } +}); + +// packages/isomorphic/disposable.ts +async function disposeAll(disposables) { + const copy = [...disposables]; + disposables.length = 0; + await Promise.all(copy.map((d) => d.dispose())); +} +var init_disposable = __esm({ + "packages/isomorphic/disposable.ts"() { + "use strict"; + } +}); + +// packages/playwright-core/src/server/userAgent.ts +function getUserAgent() { + if (cachedUserAgent) + return cachedUserAgent; + try { + cachedUserAgent = determineUserAgent(); + } catch (e) { + cachedUserAgent = "Playwright/unknown"; + } + return cachedUserAgent; +} +function determineUserAgent() { + let osIdentifier = "unknown"; + let osVersion = "unknown"; + if (process.platform === "win32") { + const version3 = import_os4.default.release().split("."); + osIdentifier = "windows"; + osVersion = `${version3[0]}.${version3[1]}`; + } else if (process.platform === "darwin") { + const version3 = (0, import_child_process2.execSync)("sw_vers -productVersion", { stdio: ["ignore", "pipe", "ignore"] }).toString().trim().split("."); + osIdentifier = "macOS"; + osVersion = `${version3[0]}.${version3[1]}`; + } else if (process.platform === "linux") { + const distroInfo = getLinuxDistributionInfoSync(); + if (distroInfo) { + osIdentifier = distroInfo.id || "linux"; + osVersion = distroInfo.version || "unknown"; + } else { + osIdentifier = "linux"; + } + } + const additionalTokens = []; + if (process.env.CI) + additionalTokens.push("CI/1"); + const serializedTokens = additionalTokens.length ? " " + additionalTokens.join(" ") : ""; + const { embedderName, embedderVersion } = getEmbedderName(); + return `Playwright/${getPlaywrightVersion()} (${import_os4.default.arch()}; ${osIdentifier} ${osVersion}) ${embedderName}/${embedderVersion}${serializedTokens}`; +} +function getEmbedderName() { + let embedderName = "unknown"; + let embedderVersion = "unknown"; + if (!process.env.PW_LANG_NAME) { + embedderName = "node"; + embedderVersion = process.version.substring(1).split(".").slice(0, 2).join("."); + } else if (["node", "python", "java", "csharp"].includes(process.env.PW_LANG_NAME)) { + embedderName = process.env.PW_LANG_NAME; + embedderVersion = process.env.PW_LANG_NAME_VERSION ?? "unknown"; + } + return { embedderName, embedderVersion }; +} +function getPlaywrightVersion(majorMinorOnly = false) { + const version3 = process.env.PW_VERSION_OVERRIDE || packageJSON.version; + return majorMinorOnly ? version3.split(".").slice(0, 2).join(".") : version3; +} +var import_child_process2, import_os4, cachedUserAgent; +var init_userAgent = __esm({ + "packages/playwright-core/src/server/userAgent.ts"() { + "use strict"; + import_child_process2 = require("child_process"); + import_os4 = __toESM(require("os")); + init_linuxUtils(); + init_package(); + } +}); + +// packages/playwright-core/src/generated/clockSource.ts +var source; +var init_clockSource = __esm({ + "packages/playwright-core/src/generated/clockSource.ts"() { + "use strict"; + source = '\nvar __commonJS = obj => {\n let required = false;\n let result;\n return function __require() {\n if (!required) {\n required = true;\n let fn;\n for (const name in obj) { fn = obj[name]; break; }\n const module = { exports: {} };\n fn(module.exports, module);\n result = module.exports;\n }\n return result;\n }\n};\nvar __export = (target, all) => {for (var name in all) target[name] = all[name];};\nvar __toESM = mod => ({ ...mod, \'default\': mod });\nvar __toCommonJS = mod => ({ ...mod, __esModule: true });\n\n\n// packages/injected/src/clock.ts\nvar clock_exports = {};\n__export(clock_exports, {\n ClockController: () => ClockController,\n createClock: () => createClock,\n inject: () => inject,\n install: () => install\n});\nmodule.exports = __toCommonJS(clock_exports);\nvar ClockController = class {\n constructor(embedder) {\n this._duringTick = false;\n this._uniqueTimerId = idCounterStart;\n this.disposables = [];\n this._log = [];\n this._timers = /* @__PURE__ */ new Map();\n this._now = { time: asWallTime(0), isFixedTime: false, ticks: 0, origin: asWallTime(-1) };\n this._embedder = embedder;\n }\n uninstall() {\n this.disposables.forEach((dispose) => dispose());\n this.disposables.length = 0;\n }\n now() {\n this._replayLogOnce();\n this._syncRealTime();\n return this._now.time;\n }\n install(time) {\n this._replayLogOnce();\n this._innerInstall(asWallTime(time));\n }\n setSystemTime(time) {\n this._replayLogOnce();\n this._innerSetTime(asWallTime(time));\n }\n setFixedTime(time) {\n this._replayLogOnce();\n this._innerSetFixedTime(asWallTime(time));\n }\n performanceNow() {\n this._replayLogOnce();\n this._syncRealTime();\n return this._now.ticks;\n }\n _syncRealTime() {\n if (!this._realTime)\n return;\n const now = this._embedder.performanceNow();\n const sinceLastSync = now - this._realTime.lastSyncTicks;\n if (sinceLastSync > 0) {\n this._advanceNow(shiftTicks(this._now.ticks, sinceLastSync));\n this._realTime.lastSyncTicks = now;\n }\n }\n _innerSetTime(time) {\n this._now.time = time;\n this._now.isFixedTime = false;\n if (this._now.origin < 0)\n this._now.origin = this._now.time;\n }\n _innerInstall(time) {\n if (this._now.origin < 0)\n this._now.ticks = 0;\n this._innerSetTime(time);\n }\n _innerSetFixedTime(time) {\n this._innerSetTime(time);\n this._now.isFixedTime = true;\n }\n _advanceNow(to) {\n if (this._now.ticks > to) {\n return;\n }\n if (!this._now.isFixedTime)\n this._now.time = asWallTime(this._now.time + to - this._now.ticks);\n this._now.ticks = to;\n }\n async log(type, time, param) {\n this._log.push({ type, time, param });\n }\n async runFor(ticks) {\n this._replayLogOnce();\n if (ticks < 0)\n throw new TypeError("Negative ticks are not supported");\n await this._runWithDisabledRealTimeSync(async () => {\n await this._runTo(shiftTicks(this._now.ticks, ticks));\n });\n }\n async _runTo(to) {\n to = Math.ceil(to);\n if (this._now.ticks > to)\n return;\n let firstException;\n while (true) {\n const result = await this._callFirstTimer(to);\n if (!result.timerFound)\n break;\n firstException = firstException || result.error;\n }\n this._advanceNow(to);\n if (firstException)\n throw firstException;\n }\n async pauseAt(time) {\n this._replayLogOnce();\n await this._innerPause();\n const toConsume = time - this._now.time;\n await this._innerFastForwardTo(shiftTicks(this._now.ticks, toConsume));\n return toConsume;\n }\n async _innerPause() {\n var _a;\n this._realTime = void 0;\n await ((_a = this._currentRealTimeTimer) == null ? void 0 : _a.dispose());\n this._currentRealTimeTimer = void 0;\n }\n resume() {\n this._replayLogOnce();\n this._innerResume();\n }\n _innerResume() {\n const now = this._embedder.performanceNow();\n this._realTime = { startTicks: now, lastSyncTicks: now };\n this._updateRealTimeTimer();\n }\n _updateRealTimeTimer() {\n var _a;\n if ((_a = this._currentRealTimeTimer) == null ? void 0 : _a.promise) {\n return;\n }\n const firstTimer = this._firstTimer();\n const nextTick = Math.min(firstTimer ? firstTimer.callAt : this._now.ticks + maxTimeout, this._now.ticks + 100);\n const callAt = this._currentRealTimeTimer ? Math.min(this._currentRealTimeTimer.callAt, nextTick) : nextTick;\n if (this._currentRealTimeTimer) {\n this._currentRealTimeTimer.cancel();\n this._currentRealTimeTimer = void 0;\n }\n const realTimeTimer = {\n callAt,\n promise: void 0,\n cancel: this._embedder.setTimeout(() => {\n this._syncRealTime();\n realTimeTimer.promise = this._runTo(this._now.ticks).catch((e) => console.error(e));\n void realTimeTimer.promise.then(() => {\n this._currentRealTimeTimer = void 0;\n if (this._realTime)\n this._updateRealTimeTimer();\n });\n }, callAt - this._now.ticks),\n dispose: async () => {\n realTimeTimer.cancel();\n await realTimeTimer.promise;\n }\n };\n this._currentRealTimeTimer = realTimeTimer;\n }\n async _runWithDisabledRealTimeSync(fn) {\n if (!this._realTime) {\n await fn();\n return;\n }\n await this._innerPause();\n try {\n await fn();\n } finally {\n this._innerResume();\n }\n }\n async fastForward(ticks) {\n this._replayLogOnce();\n await this._runWithDisabledRealTimeSync(async () => {\n await this._innerFastForwardTo(shiftTicks(this._now.ticks, ticks | 0));\n });\n }\n async _innerFastForwardTo(to) {\n if (to < this._now.ticks)\n throw new Error("Cannot fast-forward to the past");\n for (const timer of this._timers.values()) {\n if (to > timer.callAt)\n timer.callAt = to;\n }\n await this._runTo(to);\n }\n addTimer(options) {\n this._replayLogOnce();\n if (options.type === "AnimationFrame" /* AnimationFrame */ && !options.func)\n throw new Error("Callback must be provided to requestAnimationFrame calls");\n if (options.type === "IdleCallback" /* IdleCallback */ && !options.func)\n throw new Error("Callback must be provided to requestIdleCallback calls");\n if (["Timeout" /* Timeout */, "Interval" /* Interval */].includes(options.type) && !options.func && options.delay === void 0)\n throw new Error("Callback must be provided to timer calls");\n let delay = options.delay ? +options.delay : 0;\n if (!Number.isFinite(delay))\n delay = 0;\n delay = delay > maxTimeout ? 1 : delay;\n delay = Math.max(0, delay);\n const timer = {\n type: options.type,\n func: options.func,\n args: options.args || [],\n delay,\n callAt: shiftTicks(this._now.ticks, delay || (this._duringTick ? 1 : 0)),\n createdAt: this._now.ticks,\n id: this._uniqueTimerId++,\n error: new Error()\n };\n this._timers.set(timer.id, timer);\n if (this._realTime)\n this._updateRealTimeTimer();\n return timer.id;\n }\n countTimers() {\n return this._timers.size;\n }\n _firstTimer(beforeTick) {\n let firstTimer = null;\n for (const timer of this._timers.values()) {\n const isInRange = beforeTick === void 0 || timer.callAt <= beforeTick;\n if (isInRange && (!firstTimer || compareTimers(firstTimer, timer) === 1))\n firstTimer = timer;\n }\n return firstTimer;\n }\n _takeFirstTimer(beforeTick) {\n const timer = this._firstTimer(beforeTick);\n if (!timer)\n return null;\n this._advanceNow(timer.callAt);\n if (timer.type === "Interval" /* Interval */)\n timer.callAt = shiftTicks(timer.callAt, timer.delay);\n else\n this._timers.delete(timer.id);\n return timer;\n }\n async _callFirstTimer(beforeTick) {\n const timer = this._takeFirstTimer(beforeTick);\n if (!timer)\n return { timerFound: false };\n this._duringTick = true;\n try {\n if (typeof timer.func !== "function") {\n let error2;\n try {\n (() => {\n globalThis.eval(timer.func);\n })();\n } catch (e) {\n error2 = e;\n }\n await new Promise((f) => this._embedder.setTimeout(f));\n return { timerFound: true, error: error2 };\n }\n let args = timer.args;\n if (timer.type === "AnimationFrame" /* AnimationFrame */)\n args = [this._now.ticks];\n else if (timer.type === "IdleCallback" /* IdleCallback */)\n args = [{ didTimeout: false, timeRemaining: () => 0 }];\n let error;\n try {\n timer.func.apply(null, args);\n } catch (e) {\n error = e;\n }\n await new Promise((f) => this._embedder.setTimeout(f));\n return { timerFound: true, error };\n } finally {\n this._duringTick = false;\n }\n }\n getTimeToNextFrame() {\n this._replayLogOnce();\n return 16 - this._now.ticks % 16;\n }\n clearTimer(timerId, type) {\n this._replayLogOnce();\n if (!timerId) {\n return;\n }\n const id = Number(timerId);\n if (Number.isNaN(id) || id < idCounterStart) {\n const handlerName = getClearHandler(type);\n new Error(`Clock: ${handlerName} was invoked to clear a native timer instead of one created by the clock library.`);\n }\n const timer = this._timers.get(id);\n if (timer) {\n if (timer.type === type || timer.type === "Timeout" && type === "Interval" || timer.type === "Interval" && type === "Timeout") {\n this._timers.delete(id);\n } else {\n const clear = getClearHandler(type);\n const schedule = getScheduleHandler(timer.type);\n throw new Error(\n `Cannot clear timer: timer created with ${schedule}() but cleared with ${clear}()`\n );\n }\n }\n }\n _replayLogOnce() {\n if (!this._log.length)\n return;\n let lastLogTime = -1;\n let isPaused = false;\n for (const { type, time, param } of this._log) {\n if (!isPaused && lastLogTime !== -1)\n this._advanceNow(shiftTicks(this._now.ticks, time - lastLogTime));\n lastLogTime = time;\n if (type === "install") {\n this._innerInstall(asWallTime(param));\n } else if (type === "fastForward" || type === "runFor") {\n this._advanceNow(shiftTicks(this._now.ticks, param));\n } else if (type === "pauseAt") {\n isPaused = true;\n this._innerSetTime(asWallTime(param));\n } else if (type === "resume") {\n isPaused = false;\n } else if (type === "setFixedTime") {\n this._innerSetFixedTime(asWallTime(param));\n } else if (type === "setSystemTime") {\n this._innerSetTime(asWallTime(param));\n }\n }\n if (!isPaused) {\n if (lastLogTime > 0)\n this._advanceNow(shiftTicks(this._now.ticks, this._embedder.dateNow() - lastLogTime));\n this._innerResume();\n } else {\n this._realTime = void 0;\n }\n this._log.length = 0;\n }\n};\nfunction mirrorDateProperties(target, source) {\n for (const prop in source) {\n if (source.hasOwnProperty(prop))\n target[prop] = source[prop];\n }\n target.toString = () => source.toString();\n target.prototype = source.prototype;\n target.parse = source.parse;\n target.UTC = source.UTC;\n target.prototype.toUTCString = source.prototype.toUTCString;\n target.isFake = true;\n return target;\n}\nfunction createDate(clock, NativeDate) {\n function ClockDate(year, month, date, hour, minute, second, ms) {\n if (!(this instanceof ClockDate))\n return new NativeDate(clock.now()).toString();\n switch (arguments.length) {\n case 0:\n return new NativeDate(clock.now());\n case 1:\n return new NativeDate(year);\n case 2:\n return new NativeDate(year, month);\n case 3:\n return new NativeDate(year, month, date);\n case 4:\n return new NativeDate(year, month, date, hour);\n case 5:\n return new NativeDate(year, month, date, hour, minute);\n case 6:\n return new NativeDate(\n year,\n month,\n date,\n hour,\n minute,\n second\n );\n default:\n return new NativeDate(\n year,\n month,\n date,\n hour,\n minute,\n second,\n ms\n );\n }\n }\n ClockDate.now = () => clock.now();\n return mirrorDateProperties(ClockDate, NativeDate);\n}\nfunction createIntl(clock, NativeIntl) {\n const ClockIntl = {};\n for (const key of Object.getOwnPropertyNames(NativeIntl))\n ClockIntl[key] = NativeIntl[key];\n ClockIntl.DateTimeFormat = function(...args) {\n const realFormatter = new NativeIntl.DateTimeFormat(...args);\n const formatter = {\n formatRange: realFormatter.formatRange.bind(realFormatter),\n formatRangeToParts: realFormatter.formatRangeToParts.bind(realFormatter),\n resolvedOptions: realFormatter.resolvedOptions.bind(realFormatter),\n format: (date) => realFormatter.format(date || clock.now()),\n formatToParts: (date) => realFormatter.formatToParts(date || clock.now())\n };\n return formatter;\n };\n ClockIntl.DateTimeFormat.prototype = Object.create(\n NativeIntl.DateTimeFormat.prototype\n );\n ClockIntl.DateTimeFormat.supportedLocalesOf = NativeIntl.DateTimeFormat.supportedLocalesOf;\n return ClockIntl;\n}\nfunction compareTimers(a, b) {\n if (a.callAt < b.callAt)\n return -1;\n if (a.callAt > b.callAt)\n return 1;\n if (a.type === "Immediate" /* Immediate */ && b.type !== "Immediate" /* Immediate */)\n return -1;\n if (a.type !== "Immediate" /* Immediate */ && b.type === "Immediate" /* Immediate */)\n return 1;\n if (a.createdAt < b.createdAt)\n return -1;\n if (a.createdAt > b.createdAt)\n return 1;\n if (a.id < b.id)\n return -1;\n if (a.id > b.id)\n return 1;\n}\nvar maxTimeout = Math.pow(2, 31) - 1;\nvar idCounterStart = 1e12;\nfunction platformOriginals(globalObject) {\n const raw = {\n setTimeout: globalObject.setTimeout,\n clearTimeout: globalObject.clearTimeout,\n setInterval: globalObject.setInterval,\n clearInterval: globalObject.clearInterval,\n requestAnimationFrame: globalObject.requestAnimationFrame ? globalObject.requestAnimationFrame : void 0,\n cancelAnimationFrame: globalObject.cancelAnimationFrame ? globalObject.cancelAnimationFrame : void 0,\n requestIdleCallback: globalObject.requestIdleCallback ? globalObject.requestIdleCallback : void 0,\n cancelIdleCallback: globalObject.cancelIdleCallback ? globalObject.cancelIdleCallback : void 0,\n Date: globalObject.Date,\n performance: globalObject.performance,\n Intl: globalObject.Intl,\n AbortSignal: globalObject.AbortSignal\n };\n const bound = { ...raw };\n for (const key of Object.keys(bound)) {\n if (key !== "Date" && key !== "AbortSignal" && typeof bound[key] === "function")\n bound[key] = bound[key].bind(globalObject);\n }\n return { raw, bound };\n}\nfunction getScheduleHandler(type) {\n if (type === "IdleCallback" || type === "AnimationFrame")\n return `request${type}`;\n return `set${type}`;\n}\nfunction createApi(clock, originals, browserName) {\n return {\n setTimeout: (func, timeout, ...args) => {\n const delay = timeout ? +timeout : timeout;\n return clock.addTimer({\n type: "Timeout" /* Timeout */,\n func,\n args,\n delay\n });\n },\n clearTimeout: (timerId) => {\n if (timerId)\n clock.clearTimer(timerId, "Timeout" /* Timeout */);\n },\n setInterval: (func, timeout, ...args) => {\n const delay = timeout ? +timeout : timeout;\n return clock.addTimer({\n type: "Interval" /* Interval */,\n func,\n args,\n delay\n });\n },\n clearInterval: (timerId) => {\n if (timerId)\n return clock.clearTimer(timerId, "Interval" /* Interval */);\n },\n requestAnimationFrame: (callback) => {\n return clock.addTimer({\n type: "AnimationFrame" /* AnimationFrame */,\n func: callback,\n delay: clock.getTimeToNextFrame()\n });\n },\n cancelAnimationFrame: (timerId) => {\n if (timerId)\n return clock.clearTimer(timerId, "AnimationFrame" /* AnimationFrame */);\n },\n requestIdleCallback: (callback, options) => {\n let timeToNextIdlePeriod = 0;\n if (clock.countTimers() > 0)\n timeToNextIdlePeriod = 50;\n return clock.addTimer({\n type: "IdleCallback" /* IdleCallback */,\n func: callback,\n delay: (options == null ? void 0 : options.timeout) ? Math.min(options == null ? void 0 : options.timeout, timeToNextIdlePeriod) : timeToNextIdlePeriod\n });\n },\n cancelIdleCallback: (timerId) => {\n if (timerId)\n return clock.clearTimer(timerId, "IdleCallback" /* IdleCallback */);\n },\n Intl: originals.Intl ? createIntl(clock, originals.Intl) : void 0,\n Date: createDate(clock, originals.Date),\n performance: originals.performance ? fakePerformance(clock, originals.performance) : void 0,\n AbortSignal: originals.AbortSignal ? fakeAbortSignal(clock, originals.AbortSignal, browserName) : void 0\n };\n}\nfunction getClearHandler(type) {\n if (type === "IdleCallback" || type === "AnimationFrame")\n return `cancel${type}`;\n return `clear${type}`;\n}\nvar FakePerformanceEntry = class {\n constructor(name, entryType, startTime, duration) {\n this.name = name;\n this.entryType = entryType;\n this.startTime = startTime;\n this.duration = duration;\n }\n toJSON() {\n return JSON.stringify({ ...this });\n }\n};\nfunction fakePerformance(clock, performance) {\n const result = {\n now: () => clock.performanceNow()\n };\n result.__defineGetter__("timeOrigin", () => clock._now.origin || 0);\n for (const key of Object.keys(performance.__proto__)) {\n if (key === "now" || key === "timeOrigin")\n continue;\n if (key === "getEntries" || key === "getEntriesByName" || key === "getEntriesByType")\n result[key] = () => [];\n else if (key === "mark")\n result[key] = (name) => new FakePerformanceEntry(name, "mark", 0, 0);\n else if (key === "measure")\n result[key] = (name) => new FakePerformanceEntry(name, "measure", 0, 50);\n else\n result[key] = () => {\n };\n }\n return result;\n}\nfunction fakeAbortSignal(clock, abortSignal, browserName) {\n Object.defineProperty(abortSignal, "timeout", {\n value(ms) {\n const controller = new AbortController();\n clock.addTimer({\n delay: ms,\n type: "Timeout" /* Timeout */,\n func: () => controller.abort(\n new DOMException(\n browserName === "chromium" ? "signal timed out" : "The operation timed out.",\n "TimeoutError"\n )\n )\n });\n return controller.signal;\n }\n });\n return abortSignal;\n}\nfunction createClock(globalObject, config = {}) {\n const originals = platformOriginals(globalObject);\n const embedder = {\n dateNow: () => originals.raw.Date.now(),\n performanceNow: () => Math.ceil(originals.raw.performance.now()),\n setTimeout: (task, timeout) => {\n const timerId = originals.bound.setTimeout(task, timeout);\n return () => originals.bound.clearTimeout(timerId);\n },\n setInterval: (task, delay) => {\n const intervalId = originals.bound.setInterval(task, delay);\n return () => originals.bound.clearInterval(intervalId);\n }\n };\n const clock = new ClockController(embedder);\n const api = createApi(clock, originals.bound, config.browserName);\n return { clock, api, originals: originals.raw };\n}\nfunction install(globalObject, config = {}) {\n var _a, _b;\n if ((_a = globalObject.Date) == null ? void 0 : _a.isFake) {\n throw new TypeError(`Can\'t install fake timers twice on the same global object.`);\n }\n const { clock, api, originals } = createClock(globalObject, config);\n const toFake = ((_b = config.toFake) == null ? void 0 : _b.length) ? config.toFake : Object.keys(originals);\n for (const method of toFake) {\n if (method === "Date") {\n globalObject.Date = mirrorDateProperties(api.Date, globalObject.Date);\n } else if (method === "Intl") {\n globalObject.Intl = api[method];\n } else if (method === "AbortSignal") {\n globalObject.AbortSignal = api[method];\n } else if (method === "performance") {\n globalObject.performance = api[method];\n const kEventTimeStamp = Symbol("playwrightEventTimeStamp");\n Object.defineProperty(Event.prototype, "timeStamp", {\n get() {\n var _a2;\n if (!this[kEventTimeStamp])\n this[kEventTimeStamp] = (_a2 = api.performance) == null ? void 0 : _a2.now();\n return this[kEventTimeStamp];\n }\n });\n } else {\n globalObject[method] = (...args) => {\n return api[method].apply(api, args);\n };\n }\n clock.disposables.push(() => {\n globalObject[method] = originals[method];\n });\n }\n return { clock, api, originals };\n}\nfunction inject(globalObject, browserName) {\n const builtins = platformOriginals(globalObject).bound;\n const { clock: controller } = install(globalObject, { browserName });\n controller.resume();\n return {\n controller,\n builtins\n };\n}\nfunction asWallTime(n) {\n return n;\n}\nfunction shiftTicks(ticks, ms) {\n return ticks + ms;\n}\n'; + } +}); + +// packages/playwright-core/src/protocol/serializers.ts +function parseSerializedValue(value2, handles) { + return innerParseSerializedValue(value2, handles, /* @__PURE__ */ new Map(), []); +} +function innerParseSerializedValue(value2, handles, refs, accessChain) { + if (value2.ref !== void 0) + return refs.get(value2.ref); + if (value2.n !== void 0) + return value2.n; + if (value2.s !== void 0) + return value2.s; + if (value2.b !== void 0) + return value2.b; + if (value2.v !== void 0) { + if (value2.v === "undefined") + return void 0; + if (value2.v === "null") + return null; + if (value2.v === "NaN") + return NaN; + if (value2.v === "Infinity") + return Infinity; + if (value2.v === "-Infinity") + return -Infinity; + if (value2.v === "-0") + return -0; + } + if (value2.d !== void 0) + return new Date(value2.d); + if (value2.u !== void 0) + return new URL(value2.u); + if (value2.bi !== void 0) + return BigInt(value2.bi); + if (value2.e !== void 0) { + const error = new Error(value2.e.m); + error.name = value2.e.n; + error.stack = value2.e.s; + return error; + } + if (value2.r !== void 0) + return new RegExp(value2.r.p, value2.r.f); + if (value2.ta !== void 0) { + const ctor = typedArrayKindToConstructor[value2.ta.k]; + return new ctor(value2.ta.b.buffer, value2.ta.b.byteOffset, value2.ta.b.length / ctor.BYTES_PER_ELEMENT); + } + if (value2.a !== void 0) { + const result2 = []; + refs.set(value2.id, result2); + for (let i = 0; i < value2.a.length; i++) + result2.push(innerParseSerializedValue(value2.a[i], handles, refs, [...accessChain, i])); + return result2; + } + if (value2.o !== void 0) { + const result2 = {}; + refs.set(value2.id, result2); + for (const { k, v } of value2.o) + result2[k] = innerParseSerializedValue(v, handles, refs, [...accessChain, k]); + return result2; + } + if (value2.h !== void 0) { + if (handles === void 0) + throw new Error("Unexpected handle"); + return handles[value2.h]; + } + throw new Error(`Attempting to deserialize unexpected value${accessChainToDisplayString(accessChain)}: ${value2}`); +} +function serializeValue(value2, handleSerializer) { + return innerSerializeValue(value2, handleSerializer, { lastId: 0, visited: /* @__PURE__ */ new Map() }, []); +} +function innerSerializeValue(value2, handleSerializer, visitorInfo, accessChain) { + const handle = handleSerializer(value2); + if ("fallThrough" in handle) + value2 = handle.fallThrough; + else + return handle; + if (typeof value2 === "symbol") + return { v: "undefined" }; + if (Object.is(value2, void 0)) + return { v: "undefined" }; + if (Object.is(value2, null)) + return { v: "null" }; + if (Object.is(value2, NaN)) + return { v: "NaN" }; + if (Object.is(value2, Infinity)) + return { v: "Infinity" }; + if (Object.is(value2, -Infinity)) + return { v: "-Infinity" }; + if (Object.is(value2, -0)) + return { v: "-0" }; + if (typeof value2 === "boolean") + return { b: value2 }; + if (typeof value2 === "number") + return { n: value2 }; + if (typeof value2 === "string") + return { s: value2 }; + if (typeof value2 === "bigint") + return { bi: value2.toString() }; + if (isError2(value2)) + return { e: { n: value2.name, m: value2.message, s: value2.stack || "" } }; + if (isDate(value2)) + return { d: value2.toJSON() }; + if (isURL(value2)) + return { u: value2.toJSON() }; + if (isRegExp4(value2)) + return { r: { p: value2.source, f: value2.flags } }; + const typedArrayKind = constructorToTypedArrayKind.get(value2.constructor); + if (typedArrayKind) + return { ta: { b: Buffer.from(value2.buffer, value2.byteOffset, value2.byteLength), k: typedArrayKind } }; + const id = visitorInfo.visited.get(value2); + if (id) + return { ref: id }; + if (Array.isArray(value2)) { + const a = []; + const id2 = ++visitorInfo.lastId; + visitorInfo.visited.set(value2, id2); + for (let i = 0; i < value2.length; ++i) + a.push(innerSerializeValue(value2[i], handleSerializer, visitorInfo, [...accessChain, i])); + return { a, id: id2 }; + } + if (typeof value2 === "object") { + const o = []; + const id2 = ++visitorInfo.lastId; + visitorInfo.visited.set(value2, id2); + for (const name of Object.keys(value2)) + o.push({ k: name, v: innerSerializeValue(value2[name], handleSerializer, visitorInfo, [...accessChain, name]) }); + return { o, id: id2 }; + } + throw new Error(`Attempting to serialize unexpected value${accessChainToDisplayString(accessChain)}: ${value2}`); +} +function accessChainToDisplayString(accessChain) { + const chainString = accessChain.map((accessor, i) => { + if (typeof accessor === "string") + return i ? `.${accessor}` : accessor; + return `[${accessor}]`; + }).join(""); + return chainString.length > 0 ? ` at position "${chainString}"` : ""; +} +function isRegExp4(obj) { + return obj instanceof RegExp || Object.prototype.toString.call(obj) === "[object RegExp]"; +} +function isDate(obj) { + return obj instanceof Date || Object.prototype.toString.call(obj) === "[object Date]"; +} +function isURL(obj) { + return obj instanceof URL || Object.prototype.toString.call(obj) === "[object URL]"; +} +function isError2(obj) { + const proto = obj ? Object.getPrototypeOf(obj) : null; + return obj instanceof Error || proto?.name === "Error" || proto && isError2(proto); +} +var typedArrayKindToConstructor, constructorToTypedArrayKind; +var init_serializers = __esm({ + "packages/playwright-core/src/protocol/serializers.ts"() { + "use strict"; + typedArrayKindToConstructor = { + i8: Int8Array, + ui8: Uint8Array, + ui8c: Uint8ClampedArray, + i16: Int16Array, + ui16: Uint16Array, + i32: Int32Array, + ui32: Uint32Array, + f32: Float32Array, + f64: Float64Array, + bi64: BigInt64Array, + bui64: BigUint64Array + }; + constructorToTypedArrayKind = new Map(Object.entries(typedArrayKindToConstructor).map(([k, v]) => [v, k])); + } +}); + +// packages/playwright-core/src/server/errors.ts +function isTargetClosedError(error) { + return error instanceof TargetClosedError || error.name === "TargetClosedError"; +} +function serializeError(e) { + if (isError(e)) + return { error: { message: e.message, stack: e.stack, name: e.name } }; + return { value: serializeValue(e, (value2) => ({ fallThrough: value2 })) }; +} +function parseError(error) { + if (!error.error) { + if (error.value === void 0) + throw new Error("Serialized error must have either an error or a value"); + return parseSerializedValue(error.value, void 0); + } + const e = new Error(error.error.message); + e.stack = error.error.stack || ""; + e.name = error.error.name; + return e; +} +var CustomError, TimeoutError, TargetClosedError; +var init_errors = __esm({ + "packages/playwright-core/src/server/errors.ts"() { + "use strict"; + init_rtti(); + init_serializers(); + CustomError = class extends Error { + constructor(message) { + super(message); + this.name = this.constructor.name; + } + }; + TimeoutError = class extends CustomError { + }; + TargetClosedError = class extends CustomError { + constructor(cause, logs) { + super((cause || "Target page, context or browser has been closed") + (logs || "")); + } + }; + } +}); + +// packages/playwright-core/src/server/progress.ts +function isAbortError(error) { + return error instanceof TimeoutError || !!error[kAbortErrorSymbol]; +} +async function raceUncancellableOperationWithCleanup(progress2, run, cleanup) { + let aborted = false; + try { + return await progress2.race(run().then(async (t) => { + if (aborted) + await cleanup(t); + return t; + })); + } catch (error) { + aborted = true; + throw error; + } +} +var ProgressController, kAbortErrorSymbol, nullProgress; +var init_progress = __esm({ + "packages/playwright-core/src/server/progress.ts"() { + "use strict"; + init_manualPromise(); + init_assert(); + init_time(); + init_debugLogger(); + init_errors(); + ProgressController = class _ProgressController { + constructor(metadata, onCallLog) { + this._forceAbortPromise = new ManualPromise(); + this._donePromise = new ManualPromise(); + this._state = "before"; + this.metadata = metadata || { id: "", startTime: 0, endTime: 0, type: "Internal", method: "", params: {}, log: [], internal: true }; + this._onCallLog = onCallLog; + this._forceAbortPromise.catch((e) => null); + this._controller = new AbortController(); + } + static createForSdkObject(sdkObject, callMetadata) { + const logName = sdkObject.logName || "api"; + return new _ProgressController(callMetadata, (message) => { + if (logName === "api" && sdkObject.attribution.playwright?.options.isInternalPlaywright) + return; + debugLogger.log(logName, message); + sdkObject.instrumentation.onCallLog(sdkObject, callMetadata, logName, message); + }); + } + async abort(error) { + if (this._state === "running") { + error[kAbortErrorSymbol] = true; + this._state = { error }; + this._forceAbortPromise.reject(error); + this._controller.abort(error); + } + await this._donePromise; + } + async run(task, timeout) { + const deadline = timeout ? monotonicTime() + timeout : 0; + assert(this._state === "before"); + this._state = "running"; + let timer; + let outerProgress; + let allowConcurrent = false; + const progress2 = { + timeout: timeout ?? 0, + deadline, + disableTimeout: () => { + clearTimeout(timer); + }, + log: (message) => { + if (this._state === "running") + this.metadata.log.push(message); + this._onCallLog?.(message); + }, + metadata: this.metadata, + setAllowConcurrentOrNestedRaces: (allow) => { + allowConcurrent = allow; + }, + race: (promise) => { + if (process.env.PW_DETECT_NESTED_PROGRESS) { + const innerProgress = new Error().stack; + if (outerProgress && !allowConcurrent && outerProgress !== innerProgress) { + console.error("Cannot call race() inside another race()"); + console.error("<<<<>>>>:", outerProgress); + console.error("<<<<>>>>:", innerProgress); + } + outerProgress = innerProgress; + } + const promises = Array.isArray(promise) ? promise : [promise]; + if (!promises.length) + return Promise.resolve(); + return Promise.race([...promises, this._forceAbortPromise]).finally(() => outerProgress = void 0); + }, + wait: async (timeout2) => { + let timer2; + const promise = new Promise((f) => timer2 = setTimeout(f, timeout2)); + return progress2.race(promise).finally(() => clearTimeout(timer2)); + }, + signal: this._controller.signal + }; + if (deadline) { + const timeoutError = new TimeoutError(`Timeout ${timeout}ms exceeded.`); + timer = setTimeout(() => { + if (this.metadata.pauseStartTime && !this.metadata.pauseEndTime) + return; + if (this._state === "running") { + this._state = { error: timeoutError }; + this._forceAbortPromise.reject(timeoutError); + this._controller.abort(timeoutError); + } + }, deadline - monotonicTime()); + } + try { + const result2 = await task(progress2); + this._state = "finished"; + return result2; + } catch (error) { + this._state = { error }; + throw error; + } finally { + clearTimeout(timer); + this._donePromise.resolve(); + } + } + }; + kAbortErrorSymbol = Symbol("kAbortError"); + nullProgress = { + timeout: 0, + deadline: 0, + disableTimeout() { + }, + log() { + }, + race(promise) { + const promises = Array.isArray(promise) ? promise : [promise]; + return Promise.race(promises); + }, + wait: async (timeout) => await new Promise((f) => setTimeout(f, timeout)), + signal: new AbortController().signal, + metadata: { + id: "", + startTime: 0, + endTime: 0, + type: "", + method: "", + params: {}, + log: [], + internal: true + }, + setAllowConcurrentOrNestedRaces() { + } + }; + } +}); + +// packages/playwright-core/src/server/clock.ts +function parseTicks(value2) { + if (typeof value2 === "number") + return value2; + if (!value2) + return 0; + const str = value2; + const strings = str.split(":"); + const l = strings.length; + let i = l; + let ms = 0; + let parsed; + if (l > 3 || !/^(\d\d:){0,2}\d\d?$/.test(str)) { + throw new Error( + `Clock only understands numbers, 'mm:ss' and 'hh:mm:ss'` + ); + } + while (i--) { + parsed = parseInt(strings[i], 10); + if (parsed >= 60) + throw new Error(`Invalid time ${str}`); + ms += parsed * Math.pow(60, l - i - 1); + } + return ms * 1e3; +} +function parseTime(epoch) { + if (!epoch) + return 0; + if (typeof epoch === "number") + return epoch; + const parsed = new Date(epoch); + if (!isFinite(parsed.getTime())) + throw new Error(`Invalid date: ${epoch}`); + return parsed.getTime(); +} +var Clock; +var init_clock = __esm({ + "packages/playwright-core/src/server/clock.ts"() { + "use strict"; + init_clockSource(); + init_progress(); + Clock = class { + constructor(browserContext) { + this._initScripts = []; + this._browserContext = browserContext; + } + async uninstall(progress2) { + await progress2.race(Promise.all(this._initScripts.map((script) => script.dispose()))); + this._initScripts = []; + } + async fastForward(ticks) { + await this._installIfNeeded(); + const ticksMillis = parseTicks(ticks); + this._initScripts.push(await this._browserContext.addInitScript(nullProgress, `globalThis.__pwClock.controller.log('fastForward', ${Date.now()}, ${ticksMillis})`)); + await this._evaluateInFrames(`globalThis.__pwClock.controller.fastForward(${ticksMillis})`); + } + async install(time) { + await this._installIfNeeded(); + const timeMillis = time !== void 0 ? parseTime(time) : Date.now(); + this._initScripts.push(await this._browserContext.addInitScript(nullProgress, `globalThis.__pwClock.controller.log('install', ${Date.now()}, ${timeMillis})`)); + await this._evaluateInFrames(`globalThis.__pwClock.controller.install(${timeMillis})`); + } + async pauseAt(ticks) { + await this._installIfNeeded(); + const timeMillis = parseTime(ticks); + this._initScripts.push(await this._browserContext.addInitScript(nullProgress, `globalThis.__pwClock.controller.log('pauseAt', ${Date.now()}, ${timeMillis})`)); + await this._evaluateInFrames(`globalThis.__pwClock.controller.pauseAt(${timeMillis})`); + } + resumeNoReply() { + if (!this._initScripts.length) + return; + const doResume = async () => { + this._initScripts.push(await this._browserContext.addInitScript(nullProgress, `globalThis.__pwClock.controller.log('resume', ${Date.now()})`)); + await this._evaluateInFrames(`globalThis.__pwClock.controller.resume()`); + }; + doResume().catch(() => { + }); + } + async resume(progress2) { + await progress2.race(this._installIfNeeded()); + this._initScripts.push(await this._browserContext.addInitScript(nullProgress, `globalThis.__pwClock.controller.log('resume', ${Date.now()})`)); + await progress2.race(this._evaluateInFrames(`globalThis.__pwClock.controller.resume()`)); + } + async setFixedTime(time) { + await this._installIfNeeded(); + const timeMillis = parseTime(time); + this._initScripts.push(await this._browserContext.addInitScript(nullProgress, `globalThis.__pwClock.controller.log('setFixedTime', ${Date.now()}, ${timeMillis})`)); + await this._evaluateInFrames(`globalThis.__pwClock.controller.setFixedTime(${timeMillis})`); + } + async setSystemTime(time) { + await this._installIfNeeded(); + const timeMillis = parseTime(time); + this._initScripts.push(await this._browserContext.addInitScript(nullProgress, `globalThis.__pwClock.controller.log('setSystemTime', ${Date.now()}, ${timeMillis})`)); + await this._evaluateInFrames(`globalThis.__pwClock.controller.setSystemTime(${timeMillis})`); + } + async runFor(ticks) { + await this._installIfNeeded(); + const ticksMillis = parseTicks(ticks); + this._initScripts.push(await this._browserContext.addInitScript(nullProgress, `globalThis.__pwClock.controller.log('runFor', ${Date.now()}, ${ticksMillis})`)); + await this._evaluateInFrames(`globalThis.__pwClock.controller.runFor(${ticksMillis})`); + } + async _installIfNeeded() { + if (this._initScripts.length) + return; + const script = `(() => { + const module = {}; + ${source} + if (!globalThis.__pwClock) + globalThis.__pwClock = (module.exports.inject())(globalThis, ${JSON.stringify(this._browserContext._browser.options.name)}); + })();`; + const initScript = await this._browserContext.addInitScript(nullProgress, script); + await this._evaluateInFrames(script); + this._initScripts.push(initScript); + } + async _evaluateInFrames(script) { + await this._browserContext.safeNonStallingEvaluateInAllFrames(script, "main", { throwOnJSErrors: true }); + } + }; + } +}); + +// packages/playwright-core/src/generated/webAuthnSource.ts +var source2; +var init_webAuthnSource = __esm({ + "packages/playwright-core/src/generated/webAuthnSource.ts"() { + "use strict"; + source2 = ` +var __commonJS = obj => { + let required = false; + let result; + return function __require() { + if (!required) { + required = true; + let fn; + for (const name in obj) { fn = obj[name]; break; } + const module = { exports: {} }; + fn(module.exports, module); + result = module.exports; + } + return result; + } +}; +var __export = (target, all) => {for (var name in all) target[name] = all[name];}; +var __toESM = mod => ({ ...mod, 'default': mod }); +var __toCommonJS = mod => ({ ...mod, __esModule: true }); + + +// packages/injected/src/webAuthn.ts +var webAuthn_exports = {}; +__export(webAuthn_exports, { + inject: () => inject +}); +module.exports = __toCommonJS(webAuthn_exports); +function inject(globalThis) { + if (globalThis.__pwWebAuthnInstalled) + return; + globalThis.__pwWebAuthnInstalled = true; + const binding = globalThis.__pwWebAuthnBinding; + if (!binding || !globalThis.navigator) + return; + if (!globalThis.navigator.credentials) { + Object.defineProperty(globalThis.navigator, "credentials", { + value: { create: async () => null, get: async () => null }, + writable: true, + configurable: true + }); + } + function toBase64Url(buf) { + const bytes = buf instanceof ArrayBuffer ? new Uint8Array(buf) : new Uint8Array(buf.buffer, buf.byteOffset, buf.byteLength); + let s = ""; + for (let i = 0; i < bytes.length; i++) + s += String.fromCharCode(bytes[i]); + return globalThis.btoa(s).replaceAll("+", "-").replaceAll("/", "_").replaceAll("=", ""); + } + function fromBase64Url(s) { + let str = s.replaceAll("-", "+").replaceAll("_", "/"); + while (str.length % 4) + str += "="; + const bin = globalThis.atob(str); + const out = new Uint8Array(bin.length); + for (let i = 0; i < bin.length; i++) + out[i] = bin.charCodeAt(i); + return out.buffer; + } + const PublicKeyCredentialCtor = globalThis.PublicKeyCredential; + const AuthAttestationResponseCtor = globalThis.AuthenticatorAttestationResponse; + const AuthAssertionResponseCtor = globalThis.AuthenticatorAssertionResponse; + function defineReadonly(target, props) { + for (const k of Object.keys(props)) + Object.defineProperty(target, k, { value: props[k], enumerable: true, configurable: true }); + } + function makeAttestationResponse(clientDataJSON, attestationObject) { + const proto = (AuthAttestationResponseCtor == null ? void 0 : AuthAttestationResponseCtor.prototype) || Object.prototype; + const r = Object.create(proto); + defineReadonly(r, { clientDataJSON, attestationObject }); + r.getTransports = () => ["internal"]; + r.getAuthenticatorData = () => { + return attestationObject; + }; + r.getPublicKey = () => null; + r.getPublicKeyAlgorithm = () => -7; + return r; + } + function makeAssertionResponse(clientDataJSON, authenticatorData, signature, userHandle) { + const proto = (AuthAssertionResponseCtor == null ? void 0 : AuthAssertionResponseCtor.prototype) || Object.prototype; + const r = Object.create(proto); + defineReadonly(r, { clientDataJSON, authenticatorData, signature, userHandle }); + return r; + } + function makePublicKeyCredential(id, response) { + const proto = (PublicKeyCredentialCtor == null ? void 0 : PublicKeyCredentialCtor.prototype) || Object.prototype; + const cred = Object.create(proto); + defineReadonly(cred, { + id, + rawId: fromBase64Url(id), + type: "public-key", + authenticatorAttachment: "platform", + response + }); + cred.getClientExtensionResults = () => ({}); + cred.toJSON = () => ({ id, rawId: id, type: "public-key", response: {} }); + return cred; + } + function toBuf(x) { + if (!x) + return new ArrayBuffer(0); + if (x instanceof ArrayBuffer) + return x; + const v = x; + const out = new Uint8Array(v.byteLength); + out.set(new Uint8Array(v.buffer, v.byteOffset, v.byteLength)); + return out.buffer; + } + function failure(name, message) { + const Ctor = globalThis.DOMException || Error; + throw new Ctor(message, name); + } + const origCreate = globalThis.navigator.credentials.create.bind(globalThis.navigator.credentials); + const origGet = globalThis.navigator.credentials.get.bind(globalThis.navigator.credentials); + globalThis.navigator.credentials.create = async function(options) { + var _a, _b, _c, _d, _e, _f, _g; + if (!options || !options.publicKey) + return origCreate(options); + const pk = options.publicKey; + const req = { + type: "create", + origin: globalThis.location.origin, + challenge: toBase64Url(toBuf(pk.challenge)), + rp: { id: (_a = pk.rp) == null ? void 0 : _a.id, name: ((_b = pk.rp) == null ? void 0 : _b.name) || "" }, + user: { + id: toBase64Url(toBuf((_c = pk.user) == null ? void 0 : _c.id)), + name: ((_d = pk.user) == null ? void 0 : _d.name) || "", + displayName: ((_e = pk.user) == null ? void 0 : _e.displayName) || "" + }, + pubKeyCredParams: (pk.pubKeyCredParams || []).map((p) => ({ type: p.type, alg: p.alg })), + excludeCredentials: (pk.excludeCredentials || []).map((c) => ({ type: c.type, id: toBase64Url(toBuf(c.id)) })), + userVerification: (_f = pk.authenticatorSelection) == null ? void 0 : _f.userVerification, + residentKey: (_g = pk.authenticatorSelection) == null ? void 0 : _g.residentKey + }; + const result = await binding(req); + if (!result.ok) + failure(result.name, result.message); + const resp = makeAttestationResponse(fromBase64Url(result.clientDataJSON), fromBase64Url(result.attestationObject)); + return makePublicKeyCredential(result.id, resp); + }; + globalThis.navigator.credentials.get = async function(options) { + if (!options || !options.publicKey) + return origGet(options); + const pk = options.publicKey; + const req = { + type: "get", + origin: globalThis.location.origin, + challenge: toBase64Url(toBuf(pk.challenge)), + rpId: pk.rpId || new URL(globalThis.location.origin).hostname, + allowCredentials: (pk.allowCredentials || []).map((c) => ({ type: c.type, id: toBase64Url(toBuf(c.id)) })), + userVerification: pk.userVerification + }; + const result = await binding(req); + if (!result.ok) + failure(result.name, result.message); + const resp = makeAssertionResponse( + fromBase64Url(result.clientDataJSON), + fromBase64Url(result.authenticatorData), + fromBase64Url(result.signature), + result.userHandle ? fromBase64Url(result.userHandle) : null + ); + return makePublicKeyCredential(result.id, resp); + }; + if (PublicKeyCredentialCtor) { + PublicKeyCredentialCtor.isUserVerifyingPlatformAuthenticatorAvailable = async () => true; + PublicKeyCredentialCtor.isConditionalMediationAvailable = async () => true; + } +} +`; + } +}); + +// packages/playwright-core/src/server/credentials.ts +function toPublic(r) { + return { id: r.id, rpId: r.rpId, userHandle: r.userHandle, privateKey: r.privateKey, publicKey: r.publicKey }; +} +function randomBase64Url(bytes) { + return bufToB64Url(import_crypto6.default.randomBytes(bytes)); +} +function bufToB64Url(b) { + return b.toString("base64").replaceAll("+", "-").replaceAll("/", "_").replaceAll("=", ""); +} +function b64UrlToBuf(s) { + return Buffer.from(s, "base64url"); +} +function u32ToBytes(n) { + const b = Buffer.alloc(4); + b.writeUInt32BE(n >>> 0, 0); + return b; +} +function cborHead(major2, value2) { + const m = major2 << 5; + if (value2 < 24) + return Buffer.from([m | value2]); + if (value2 < 256) + return Buffer.from([m | 24, value2]); + if (value2 < 65536) + return Buffer.from([m | 25, value2 >> 8 & 255, value2 & 255]); + return Buffer.from([m | 26, value2 >>> 24 & 255, value2 >> 16 & 255, value2 >> 8 & 255, value2 & 255]); +} +function cborUint(v) { + return cborHead(0, v); +} +function cborNint(v) { + return cborHead(1, -1 - v); +} +function cborBytes(b) { + return Buffer.concat([cborHead(2, b.length), b]); +} +function cborText(s) { + const b = Buffer.from(s, "utf8"); + return Buffer.concat([cborHead(3, b.length), b]); +} +function cborMap(entries) { + return Buffer.concat([cborHead(5, entries.length), ...entries.flatMap(([k, v]) => [k, v])]); +} +function encodeCoseEs256PublicKey(publicKey) { + const jwk = publicKey.export({ format: "jwk" }); + const x = Buffer.from(jwk.x, "base64url"); + const y = Buffer.from(jwk.y, "base64url"); + return cborMap([ + [cborUint(1), cborUint(2)], + // kty = EC2 + [cborUint(3), cborNint(-7)], + // alg = ES256 + [cborNint(-1), cborUint(1)], + // crv = P-256 + [cborNint(-2), cborBytes(x)], + [cborNint(-3), cborBytes(y)] + ]); +} +function encodeAttestationObjectNone(authData) { + return cborMap([ + [cborText("fmt"), cborText("none")], + [cborText("attStmt"), cborMap([])], + [cborText("authData"), cborBytes(authData)] + ]); +} +var import_crypto6, kBindingName, kAuthenticatorAAGUID, Credentials; +var init_credentials = __esm({ + "packages/playwright-core/src/server/credentials.ts"() { + "use strict"; + import_crypto6 = __toESM(require("crypto")); + init_webAuthnSource(); + init_progress(); + kBindingName = "__pwWebAuthnBinding"; + kAuthenticatorAAGUID = Buffer.alloc(16); + Credentials = class { + constructor(browserContext) { + this._initScripts = []; + this._installed = false; + this._registry = /* @__PURE__ */ new Map(); + this._browserContext = browserContext; + } + async create(options) { + let privateKey = options.privateKey; + let publicKey = options.publicKey; + if (!privateKey || !publicKey) { + const pair = import_crypto6.default.generateKeyPairSync("ec", { namedCurve: "P-256" }); + privateKey = bufToB64Url(pair.privateKey.export({ format: "der", type: "pkcs8" })); + publicKey = bufToB64Url(pair.publicKey.export({ format: "der", type: "spki" })); + } + const record = { + id: options.id || randomBase64Url(16), + rpId: options.rpId, + userHandle: options.userHandle || randomBase64Url(16), + privateKey, + publicKey, + signCount: 0, + isResident: true + }; + this._registry.set(record.id, record); + return toPublic(record); + } + async get(filter) { + return [...this._registry.values()].filter((c) => { + if (filter?.rpId && c.rpId !== filter.rpId) + return false; + if (filter?.id && c.id !== filter.id) + return false; + return true; + }).map(toPublic); + } + async delete(id) { + this._registry.delete(id); + } + async dispose(progress2) { + await progress2.race(Promise.all(this._initScripts.map((s) => s.dispose()))); + this._initScripts = []; + this._installed = false; + this._registry.clear(); + } + async install(progress2) { + if (this._installed) + return; + this._installed = true; + await this._browserContext.exposeBinding(progress2, kBindingName, async (_source, payload) => { + try { + if (payload?.type === "create") + return await this._handleCreate(payload); + if (payload?.type === "get") + return this._handleGet(payload); + } catch (e) { + return { ok: false, name: "NotAllowedError", message: e.message }; + } + return { ok: false, name: "NotAllowedError", message: "Unknown WebAuthn request" }; + }); + const script = `(() => { + const module = {}; + ${source2} + module.exports.inject()(globalThis); + })();`; + const initScript = await this._browserContext.addInitScript(nullProgress, script); + this._initScripts.push(initScript); + await progress2.race(this._browserContext.safeNonStallingEvaluateInAllFrames(script, "main", { throwOnJSErrors: false })); + } + async _handleCreate(req) { + const rpId = req.rp?.id || new URL(req.origin).hostname; + const userHandle = req.user.id; + if (req.excludeCredentials?.length) { + for (const desc of req.excludeCredentials) { + if (this._registry.has(desc.id)) + return { ok: false, name: "InvalidStateError", message: "Credential excluded" }; + } + } + const pair = import_crypto6.default.generateKeyPairSync("ec", { namedCurve: "P-256" }); + const privateKey = bufToB64Url(pair.privateKey.export({ format: "der", type: "pkcs8" })); + const publicKey = bufToB64Url(pair.publicKey.export({ format: "der", type: "spki" })); + const credentialId = import_crypto6.default.randomBytes(16); + const credentialIdB64 = bufToB64Url(credentialId); + const record = { + id: credentialIdB64, + rpId, + userHandle, + privateKey, + publicKey, + signCount: 0, + isResident: req.residentKey === "required" || req.residentKey === "preferred" + }; + this._registry.set(credentialIdB64, record); + const clientDataJSON = Buffer.from(JSON.stringify({ + type: "webauthn.create", + challenge: req.challenge, + origin: req.origin, + crossOrigin: false + })); + const rpIdHash = import_crypto6.default.createHash("sha256").update(rpId).digest(); + const flags = 1 | 4 | 64; + const signCountBuf = u32ToBytes(record.signCount); + const cosePublicKey = encodeCoseEs256PublicKey(pair.publicKey); + const credIdLenBuf = Buffer.from([credentialId.length >> 8 & 255, credentialId.length & 255]); + const attestedCredentialData = Buffer.concat([kAuthenticatorAAGUID, credIdLenBuf, credentialId, cosePublicKey]); + const authData = Buffer.concat([rpIdHash, Buffer.from([flags]), signCountBuf, attestedCredentialData]); + const attestationObject = encodeAttestationObjectNone(authData); + return { + ok: true, + id: credentialIdB64, + clientDataJSON: bufToB64Url(clientDataJSON), + attestationObject: bufToB64Url(attestationObject) + }; + } + _handleGet(req) { + const rpId = req.rpId || new URL(req.origin).hostname; + let candidate; + if (req.allowCredentials?.length) { + for (const desc of req.allowCredentials) { + const c = this._registry.get(desc.id); + if (c && c.rpId === rpId) { + candidate = c; + break; + } + } + } else { + for (const c of this._registry.values()) { + if (c.rpId === rpId && c.isResident) { + candidate = c; + break; + } + } + } + if (!candidate) + return { ok: false, name: "NotAllowedError", message: "No matching credential" }; + const clientDataJSON = Buffer.from(JSON.stringify({ + type: "webauthn.get", + challenge: req.challenge, + origin: req.origin, + crossOrigin: false + })); + const rpIdHash = import_crypto6.default.createHash("sha256").update(rpId).digest(); + const flags = 1 | 4; + candidate.signCount += 1; + const signCountBuf = u32ToBytes(candidate.signCount); + const authData = Buffer.concat([rpIdHash, Buffer.from([flags]), signCountBuf]); + const clientDataHash = import_crypto6.default.createHash("sha256").update(clientDataJSON).digest(); + const toSign = Buffer.concat([authData, clientDataHash]); + const privateKey = import_crypto6.default.createPrivateKey({ key: b64UrlToBuf(candidate.privateKey), format: "der", type: "pkcs8" }); + const signature = import_crypto6.default.sign("sha256", toSign, privateKey); + return { + ok: true, + id: candidate.id, + clientDataJSON: bufToB64Url(clientDataJSON), + authenticatorData: bufToB64Url(authData), + signature: bufToB64Url(signature), + userHandle: candidate.userHandle || null + }; + } + }; + } +}); + +// packages/playwright-core/src/server/instrumentation.ts +function createRootSdkObject() { + const fakeParent = { attribution: {}, instrumentation: createInstrumentation() }; + const root = new SdkObject(fakeParent); + root.guid = ""; + return root; +} +function createInstrumentation() { + const listeners = /* @__PURE__ */ new Map(); + const lastListeners = /* @__PURE__ */ new Map(); + return new Proxy({}, { + get: (obj, prop) => { + if (typeof prop !== "string") + return obj[prop]; + if (prop === "addListener") { + return (listener, context2, options) => { + if (options?.order === "last") + lastListeners.set(listener, context2); + else + listeners.set(listener, context2); + }; + } + if (prop === "removeListener") { + return (listener) => { + listeners.delete(listener); + lastListeners.delete(listener); + }; + } + if (!prop.startsWith("on")) + return obj[prop]; + return async (sdkObject, ...params2) => { + for (const [listener, context2] of listeners) { + if (!context2 || sdkObject.attribution.context === context2) + await listener[prop]?.(sdkObject, ...params2); + } + for (const [listener, context2] of lastListeners) { + if (!context2 || sdkObject.attribution.context === context2) + await listener[prop]?.(sdkObject, ...params2); + } + }; + } + }); +} +var import_events3, SdkObject; +var init_instrumentation = __esm({ + "packages/playwright-core/src/server/instrumentation.ts"() { + "use strict"; + import_events3 = require("events"); + init_crypto(); + init_debugLogger(); + SdkObject = class extends import_events3.EventEmitter { + constructor(parent, guidPrefix, guid) { + super(); + this.guid = guid || `${guidPrefix || ""}@${createGuid()}`; + this.setMaxListeners(0); + this.attribution = { ...parent.attribution }; + this.instrumentation = parent.instrumentation; + } + apiLog(message) { + if (!this.attribution.playwright.options.isInternalPlaywright) + debugLogger.log("api", message); + } + closeReason() { + return this.attribution.worker?._closeReason || this.attribution.page?._closeReason || this.attribution.context?._closeReason || this.attribution.browser?._closeReason; + } + }; + } +}); + +// packages/playwright-core/src/server/debugger.ts +function matchesLocation(metadata, location2) { + return !!metadata.location?.file.includes(location2.file) && (location2.line === void 0 || metadata.location.line === location2.line) && (location2.column === void 0 || metadata.location.column === location2.column); +} +var symbol, Debugger; +var init_debugger = __esm({ + "packages/playwright-core/src/server/debugger.ts"() { + "use strict"; + init_protocolMetainfo(); + init_time(); + init_instrumentation(); + init_browserContext(); + symbol = Symbol("Debugger"); + Debugger = class _Debugger extends SdkObject { + constructor(context2) { + super(context2, "debugger"); + this._pauseAt = {}; + this._enabled = false; + this._pauseBeforeWaitingActions = false; + this._muted = false; + this._context = context2; + this._context[symbol] = this; + context2.instrumentation.addListener(this, context2, { order: "last" }); + this._context.once(BrowserContext.Events.Close, () => { + this._context.instrumentation.removeListener(this); + }); + } + static { + this.Events = { + PausedStateChanged: "pausedstatechanged" + }; + } + requestPause(progress2) { + if (this.isPaused()) + throw new Error("Debugger is already paused"); + this.setPauseBeforeWaitingActions(); + this.setPauseAt({ next: true }); + } + doResume(progress2) { + if (!this.isPaused()) + throw new Error("Debugger is not paused"); + this.resume(); + } + next(progress2) { + if (!this.isPaused()) + throw new Error("Debugger is not paused"); + this.setPauseBeforeWaitingActions(); + this.setPauseAt({ next: true }); + this.resume(); + } + runTo(progress2, location2) { + if (!this.isPaused()) + throw new Error("Debugger is not paused"); + this.setPauseBeforeWaitingActions(); + this.setPauseAt({ location: location2 }); + this.resume(); + } + async setMuted(muted) { + this._muted = muted; + } + async onBeforeCall(sdkObject, metadata) { + if (this._muted || metadata.internal) + return; + const metainfo = getMetainfo(metadata); + const pauseOnPauseCall = this._enabled && metadata.type === "BrowserContext" && metadata.method === "pause"; + const pauseBeforeAction = !!this._pauseAt.next && !!metainfo?.pause && (this._pauseBeforeWaitingActions || !metainfo?.isAutoWaiting); + const pauseOnLocation = !!this._pauseAt.location && matchesLocation(metadata, this._pauseAt.location); + if (pauseOnPauseCall || pauseBeforeAction || pauseOnLocation) + await this._pause(sdkObject, metadata); + } + async onBeforeInputAction(sdkObject, metadata) { + if (this._muted || metadata.internal) + return; + const metainfo = getMetainfo(metadata); + const pauseBeforeInput = !!this._pauseAt.next && !!metainfo?.pause && !!metainfo?.isAutoWaiting && !this._pauseBeforeWaitingActions; + if (pauseBeforeInput) + await this._pause(sdkObject, metadata); + } + async _pause(sdkObject, metadata) { + if (this._muted || metadata.internal) + return; + if (this._pausedCall) + return; + this._pauseAt = {}; + metadata.pauseStartTime = monotonicTime(); + const result2 = new Promise((resolve) => { + this._pausedCall = { metadata, sdkObject, resolve }; + }); + this.emit(_Debugger.Events.PausedStateChanged); + return result2; + } + resume() { + if (!this._pausedCall) + return; + this._pausedCall.metadata.pauseEndTime = monotonicTime(); + this._pausedCall.resolve(); + this._pausedCall = void 0; + this.emit(_Debugger.Events.PausedStateChanged); + } + setPauseBeforeWaitingActions() { + this._pauseBeforeWaitingActions = true; + } + setPauseAt(at = {}) { + this._enabled = true; + this._pauseAt = at; + } + isPaused(metadata) { + if (metadata) + return this._pausedCall?.metadata === metadata; + return !!this._pausedCall; + } + pausedDetails() { + return this._pausedCall; + } + }; + } +}); + +// packages/playwright-core/src/server/dialog.ts +var Dialog, DialogManager; +var init_dialog = __esm({ + "packages/playwright-core/src/server/dialog.ts"() { + "use strict"; + init_assert(); + init_instrumentation(); + Dialog = class extends SdkObject { + constructor(page, type3, message, onHandle, defaultValue) { + super(page, "dialog"); + this._handled = false; + this._page = page; + this._type = type3; + this._message = message; + this._onHandle = onHandle; + this._defaultValue = defaultValue || ""; + } + async accept(progress2, promptText) { + await progress2.race(this._accept(promptText)); + } + async dismiss(progress2) { + await progress2.race(this._dismiss()); + } + page() { + return this._page; + } + type() { + return this._type; + } + message() { + return this._message; + } + defaultValue() { + return this._defaultValue; + } + async _accept(promptText) { + assert(!this._handled, "Cannot accept dialog which is already handled!"); + this._handled = true; + this._page.browserContext.dialogManager._dialogWillClose(this); + await this._onHandle(true, promptText); + } + async _dismiss() { + assert(!this._handled, "Cannot dismiss dialog which is already handled!"); + this._handled = true; + this._page.browserContext.dialogManager._dialogWillClose(this); + await this._onHandle(false); + } + async _close() { + if (this._type === "beforeunload") + await this._accept(); + else + await this._dismiss(); + } + }; + DialogManager = class { + constructor(instrumentation) { + this._dialogHandlers = /* @__PURE__ */ new Set(); + this._openedDialogs = /* @__PURE__ */ new Set(); + this._instrumentation = instrumentation; + } + dialogDidOpen(dialog) { + for (const frame of dialog.page().frameManager.frames()) + frame.invalidateNonStallingEvaluations("JavaScript dialog interrupted evaluation"); + this._openedDialogs.add(dialog); + this._instrumentation.onDialog(dialog); + let hasHandlers = false; + for (const handler of this._dialogHandlers) { + if (handler(dialog)) + hasHandlers = true; + } + if (!hasHandlers) + dialog._close().then(() => { + }); + } + _dialogWillClose(dialog) { + this._openedDialogs.delete(dialog); + } + addDialogHandler(handler) { + this._dialogHandlers.add(handler); + } + removeDialogHandler(handler) { + this._dialogHandlers.delete(handler); + if (!this._dialogHandlers.size) { + for (const dialog of this._openedDialogs) + dialog._close().catch(() => { + }); + } + } + hasOpenDialogsForPage(page) { + return [...this._openedDialogs].some((dialog) => dialog.page() === page); + } + async closeBeforeUnloadDialogs() { + await Promise.all([...this._openedDialogs].map(async (dialog) => { + if (dialog.type() === "beforeunload") + await dialog._dismiss(); + })); + } + }; + } +}); + +// packages/playwright-core/src/server/network.ts +function filterCookies(cookies, urls) { + const parsedURLs = urls.map((s) => new URL(s)); + return cookies.filter((c) => { + if (!parsedURLs.length) + return true; + for (const parsedURL of parsedURLs) { + let domain = c.domain; + if (!domain.startsWith(".")) + domain = "." + domain; + if (!("." + parsedURL.hostname).endsWith(domain)) + continue; + if (!parsedURL.pathname.startsWith(c.path)) + continue; + if (parsedURL.protocol !== "https:" && !isLocalHostname(parsedURL.hostname) && c.secure) + continue; + return true; + } + return false; + }); +} +function isLocalHostname(hostname) { + return hostname === "localhost" || hostname.endsWith(".localhost"); +} +function isForbiddenHeader(name, value2) { + const lowerName = name.toLowerCase(); + if (FORBIDDEN_HEADER_NAMES.has(lowerName)) + return true; + if (lowerName.startsWith("proxy-")) + return true; + if (lowerName.startsWith("sec-")) + return true; + if (lowerName === "x-http-method" || lowerName === "x-http-method-override" || lowerName === "x-method-override") { + if (value2 && FORBIDDEN_METHODS.has(value2.toUpperCase())) + return true; + } + return false; +} +function applyHeadersOverrides(original, overrides) { + const forbiddenHeaders = original.filter((header) => isForbiddenHeader(header.name, header.value)); + const allowedHeaders = overrides.filter((header) => !isForbiddenHeader(header.name, header.value)); + return mergeHeaders([allowedHeaders, forbiddenHeaders]); +} +function rewriteCookies(cookies) { + return cookies.map((c) => { + assert(c.url || c.domain && c.path, "Cookie should have a url or a domain/path pair"); + assert(!(c.url && c.domain), "Cookie should have either url or domain"); + assert(!(c.url && c.path), "Cookie should have either url or path"); + assert(!(c.expires && c.expires < 0 && c.expires !== -1), "Cookie should have a valid expires, only -1 or a positive number for the unix timestamp in seconds is allowed"); + assert(!(c.expires && c.expires > 0 && c.expires > kMaxCookieExpiresDateInSeconds), "Cookie should have a valid expires, only -1 or a positive number for the unix timestamp in seconds is allowed"); + const copy = { ...c }; + if (copy.url) { + assert(copy.url !== "about:blank", `Blank page can not have cookie "${c.name}"`); + assert(!copy.url.startsWith("data:"), `Data URL page can not have cookie "${c.name}"`); + const url2 = new URL(copy.url); + copy.domain = url2.hostname; + copy.path = url2.pathname.substring(0, url2.pathname.lastIndexOf("/") + 1); + copy.secure = url2.protocol === "https:"; + } + return copy; + }); +} +function parseURL2(url2) { + try { + return new URL(url2); + } catch (e) { + return null; + } +} +function stripFragmentFromUrl(url2) { + if (!url2.includes("#")) + return url2; + return url2.substring(0, url2.indexOf("#")); +} +function statusText(status) { + return STATUS_TEXTS[String(status)] || "Unknown"; +} +function singleHeader(name, value2) { + return [{ name, value: value2 }]; +} +function mergeHeaders(headers) { + const lowerCaseToValue = /* @__PURE__ */ new Map(); + const lowerCaseToOriginalCase = /* @__PURE__ */ new Map(); + for (const h of headers) { + if (!h) + continue; + for (const { name, value: value2 } of h) { + const lower = name.toLowerCase(); + lowerCaseToOriginalCase.set(lower, name); + lowerCaseToValue.set(lower, value2); + } + } + const result2 = []; + for (const [lower, value2] of lowerCaseToValue) + result2.push({ name: lowerCaseToOriginalCase.get(lower), value: value2 }); + return result2; +} +function headersSize(headers) { + let result2 = 0; + for (const header of headers) + result2 += header.name.length + header.value.length + 4; + return result2; +} +function requestHeadersSize(headers, url2, method) { + let result2 = 4; + result2 += method.length; + result2 += new URL(url2).pathname.length; + result2 += 8; + result2 += headersSize(headers); + return result2; +} +function responseHeadersSize(headers, statusText2) { + let result2 = 4; + result2 += 8; + result2 += 3; + result2 += statusText2.length; + result2 += headersSize(headers); + result2 += 2; + return result2; +} +var FORBIDDEN_HEADER_NAMES, FORBIDDEN_METHODS, kMaxCookieExpiresDateInSeconds, Request, Route, Response2, WebSocket, STATUS_TEXTS; +var init_network2 = __esm({ + "packages/playwright-core/src/server/network.ts"() { + "use strict"; + init_manualPromise(); + init_assert(); + init_browserContext(); + init_fetch(); + init_instrumentation(); + FORBIDDEN_HEADER_NAMES = /* @__PURE__ */ new Set([ + "accept-charset", + "accept-encoding", + "access-control-request-headers", + "access-control-request-method", + "connection", + "content-length", + "cookie", + "date", + "dnt", + "expect", + "host", + "keep-alive", + "origin", + "referer", + "set-cookie", + "te", + "trailer", + "transfer-encoding", + "upgrade", + "via" + ]); + FORBIDDEN_METHODS = /* @__PURE__ */ new Set(["CONNECT", "TRACE", "TRACK"]); + kMaxCookieExpiresDateInSeconds = 253402300799; + Request = class _Request extends SdkObject { + constructor(context2, frame, serviceWorker, redirectedFrom, documentId, url2, resourceType, method, postData, headers, wallTimeMs) { + super(frame || context2, "request"); + this._response = null; + this._redirectedTo = null; + this._failureText = null; + this._frame = null; + this._serviceWorker = null; + this._rawRequestHeadersPromise = new ManualPromise(); + this._waitForResponsePromise = new ManualPromise(); + this._responseEndTiming = -1; + assert(!url2.startsWith("data:"), "Data urls should not fire requests"); + this._context = context2; + this._frame = frame; + this._serviceWorker = serviceWorker; + this._redirectedFrom = redirectedFrom; + if (redirectedFrom) + redirectedFrom._redirectedTo = this; + this._documentId = documentId; + this._url = stripFragmentFromUrl(url2); + this._resourceType = resourceType; + this._method = method; + this._postData = postData; + this._headers = headers; + this._wallTimeMs = wallTimeMs; + this._isFavicon = url2.endsWith("/favicon.ico") || !!redirectedFrom?._isFavicon; + } + static { + this.Events = { + Response: "response" + }; + } + wallTimeMs() { + return this._wallTimeMs; + } + async raceWithPageClosure(progress2, promise) { + const scope = this._serviceWorker?.openScope ?? this._frame?._page.openScope; + if (scope) + return await progress2.race(scope.race(promise)); + return await progress2.race(promise); + } + async rawRequestHeaders(progress2) { + return await this.raceWithPageClosure(progress2, this.internalRawRequestHeaders()); + } + async response(progress2) { + return await this.raceWithPageClosure(progress2, this._waitForResponse()); + } + _setFailureText(failureText) { + this._failureText = failureText; + this._waitForResponsePromise.resolve(null); + } + _applyOverrides(overrides) { + this._overrides = { ...this._overrides, ...overrides }; + return this._overrides; + } + overrides() { + return this._overrides; + } + url() { + return this._overrides?.url || this._url; + } + resourceType() { + return this._resourceType; + } + method() { + return this._overrides?.method || this._method; + } + postDataBuffer() { + return this._overrides?.postData || this._postData; + } + headers() { + return this._overrides?.headers || this._headers; + } + headerValue(name) { + const lowerCaseName = name.toLowerCase(); + return this.headers().find((h) => h.name.toLowerCase() === lowerCaseName)?.value; + } + // "null" means no raw headers available - we'll use provisional headers as raw headers. + setRawRequestHeaders(headers) { + if (!this._rawRequestHeadersPromise.isDone()) + this._rawRequestHeadersPromise.resolve(headers || this._headers); + } + async internalRawRequestHeaders() { + return this._overrides?.headers || this._rawRequestHeadersPromise; + } + _waitForResponse() { + return this._waitForResponsePromise; + } + _existingResponse() { + return this._response; + } + _setResponse(response2) { + this._response = response2; + this._waitForResponsePromise.resolve(response2); + this.emit(_Request.Events.Response, response2); + } + _finalRequest() { + return this._redirectedTo ? this._redirectedTo._finalRequest() : this; + } + frame() { + return this._frame; + } + serviceWorker() { + return this._serviceWorker; + } + isNavigationRequest() { + return !!this._documentId; + } + redirectedFrom() { + return this._redirectedFrom; + } + failure() { + if (this._failureText === null) + return null; + return { + errorText: this._failureText + }; + } + // TODO(bidi): remove once post body is available. + _setBodySize(size) { + this._bodySize = size; + } + bodySize() { + return this._bodySize || this.postDataBuffer()?.length || 0; + } + async _requestHeadersSize() { + return requestHeadersSize(await this.internalRawRequestHeaders(), this.url(), this.method()); + } + }; + Route = class extends SdkObject { + constructor(request2, delegate) { + super(request2._frame || request2._context, "route"); + this._handled = false; + this._futureHandlers = []; + this._request = request2; + this._delegate = delegate; + this._request._context.addRouteInFlight(this); + } + handle(handlers) { + this._futureHandlers = [...handlers]; + this.continue({ isFallback: true }).catch(() => { + }); + } + async removeHandler(handler) { + this._futureHandlers = this._futureHandlers.filter((h) => h !== handler); + if (handler === this._currentHandler) { + await this.continue({ isFallback: true }).catch(() => { + }); + return; + } + } + request() { + return this._request; + } + async abort(errorCode = "failed") { + this._startHandling(); + this._request._context.emit(BrowserContext.Events.RequestAborted, this._request); + await this._delegate.abort(errorCode); + this._endHandling(); + } + redirectNavigationRequest(url2) { + this._startHandling(); + assert(this._request.isNavigationRequest()); + this._request.frame().redirectNavigation(url2, this._request._documentId, this._request.headerValue("referer")); + this._endHandling(); + } + async fulfill(overrides) { + this._startHandling(); + let body = overrides.body; + let isBase64 = overrides.isBase64 || false; + if (body === void 0) { + if (overrides.fetchResponseUid) { + const buffer = this._request._context.fetchRequest.fetchResponses.get(overrides.fetchResponseUid) || APIRequestContext.findResponseBody(overrides.fetchResponseUid); + assert(buffer, "Fetch response has been disposed"); + body = buffer.toString("base64"); + isBase64 = true; + } else { + body = ""; + isBase64 = false; + } + } else if (!overrides.status || overrides.status < 200 || overrides.status >= 400) { + this._request._responseBodyOverride = { body, isBase64 }; + } + const headers = [...overrides.headers || []]; + this._maybeAddCorsHeaders(headers); + this._request._context.emit(BrowserContext.Events.RequestFulfilled, this._request); + await this._delegate.fulfill({ + status: overrides.status || 200, + headers, + body, + isBase64 + }); + this._endHandling(); + } + // See https://github.com/microsoft/playwright/issues/12929 + _maybeAddCorsHeaders(headers) { + const origin = this._request.headerValue("origin"); + if (!origin) + return; + const requestUrl = new URL(this._request.url()); + if (!requestUrl.protocol.startsWith("http")) + return; + if (requestUrl.origin === origin.trim()) + return; + const corsHeader = headers.find(({ name }) => name === "access-control-allow-origin"); + if (corsHeader) + return; + headers.push({ name: "access-control-allow-origin", value: origin }); + headers.push({ name: "access-control-allow-credentials", value: "true" }); + headers.push({ name: "vary", value: "Origin" }); + } + async continue(overrides) { + if (overrides.url) { + const newUrl = new URL(overrides.url); + const oldUrl = new URL(this._request.url()); + if (oldUrl.protocol !== newUrl.protocol) + throw new Error("New URL must have same protocol as overridden URL"); + } + if (overrides.headers) { + overrides.headers = applyHeadersOverrides(this._request._headers, overrides.headers); + } + overrides = this._request._applyOverrides(overrides); + const nextHandler = this._futureHandlers.shift(); + if (nextHandler) { + this._currentHandler = nextHandler; + nextHandler(this, this._request); + return; + } + if (!overrides.isFallback) + this._request._context.emit(BrowserContext.Events.RequestContinued, this._request); + this._startHandling(); + await this._delegate.continue(overrides); + this._endHandling(); + } + _startHandling() { + assert(!this._handled, "Route is already handled!"); + this._handled = true; + this._currentHandler = void 0; + } + _endHandling() { + this._futureHandlers = []; + this._currentHandler = void 0; + this._request._context.removeRouteInFlight(this); + } + }; + Response2 = class extends SdkObject { + constructor(request2, status, statusText2, headers, timing, getResponseBodyCallback, fromServiceWorker) { + super(request2.frame() || request2._context, "response"); + this._contentPromise = null; + this._finishedPromise = new ManualPromise(); + this._headersMap = /* @__PURE__ */ new Map(); + this._serverAddrPromise = new ManualPromise(); + this._securityDetailsPromise = new ManualPromise(); + this._rawResponseHeadersPromise = new ManualPromise(); + this._httpVersionPromise = new ManualPromise(); + this._encodedBodySizePromise = new ManualPromise(); + this._transferSizePromise = new ManualPromise(); + this._responseHeadersSizePromise = new ManualPromise(); + this._request = request2; + this._timing = timing; + this._status = status; + this._statusText = statusText2; + this._url = request2.url(); + this._headers = headers; + for (const { name, value: value2 } of this._headers) + this._headersMap.set(name.toLowerCase(), value2); + this._getResponseBodyCallback = getResponseBodyCallback; + this._request._setResponse(this); + this._fromServiceWorker = fromServiceWorker; + } + async body(progress2) { + return await this._request.raceWithPageClosure(progress2, this.internalBody()); + } + async securityDetails(progress2) { + return await this._request.raceWithPageClosure(progress2, this.internalSecurityDetails()); + } + async serverAddr(progress2) { + return await this._request.raceWithPageClosure(progress2, this.internalServerAddr()); + } + async rawResponseHeaders(progress2) { + return await this._request.raceWithPageClosure(progress2, this.internalRawResponseHeaders()); + } + async httpVersion(progress2) { + return await this._request.raceWithPageClosure(progress2, this.internalHttpVersion()); + } + async sizes(progress2) { + return await this._request.raceWithPageClosure(progress2, this.internalSizes()); + } + _serverAddrFinished(addr) { + this._serverAddrPromise.resolve(addr); + } + _securityDetailsFinished(securityDetails) { + this._securityDetailsPromise.resolve(securityDetails); + } + _requestFinished(responseEndTiming) { + this._request._responseEndTiming = Math.max(responseEndTiming, this._timing.responseStart); + if (this._timing.requestStart === -1) + this._timing.requestStart = this._request._responseEndTiming; + this._finishedPromise.resolve(); + } + _setHttpVersion(httpVersion) { + this._httpVersionPromise.resolve(httpVersion); + } + url() { + return this._url; + } + status() { + return this._status; + } + statusText() { + return this._statusText; + } + headers() { + return this._headers; + } + headerValue(name) { + return this._headersMap.get(name); + } + // "null" means no raw headers available - we'll use provisional headers as raw headers. + setRawResponseHeaders(headers) { + if (!this._rawResponseHeadersPromise.isDone()) + this._rawResponseHeadersPromise.resolve(headers || this._headers); + } + setTransferSize(size) { + this._transferSizePromise.resolve(size); + } + setEncodedBodySize(size) { + this._encodedBodySizePromise.resolve(size); + } + setResponseHeadersSize(size) { + this._responseHeadersSizePromise.resolve(size); + } + timing() { + return this._timing; + } + async internalSecurityDetails() { + return await this._securityDetailsPromise || null; + } + async internalServerAddr() { + return await this._serverAddrPromise || null; + } + async internalRawResponseHeaders() { + return await this._rawResponseHeadersPromise; + } + internalBody() { + if (!this._contentPromise) { + this._contentPromise = this._finishedPromise.then(async () => { + if (this._status >= 300 && this._status <= 399) + throw new Error("Response body is unavailable for redirect responses"); + if (this._request._responseBodyOverride) { + const { body, isBase64 } = this._request._responseBodyOverride; + return Buffer.from(body, isBase64 ? "base64" : "utf-8"); + } + return this._getResponseBodyCallback(); + }); + } + return this._contentPromise; + } + request() { + return this._request; + } + finished() { + return this._finishedPromise; + } + frame() { + return this._request.frame(); + } + async internalHttpVersion() { + const httpVersion = await this._httpVersionPromise || null; + if (!httpVersion) + return "HTTP/1.1"; + if (httpVersion === "http/1.1") + return "HTTP/1.1"; + if (httpVersion === "h2") + return "HTTP/2.0"; + return httpVersion; + } + fromServiceWorker() { + return this._fromServiceWorker; + } + async responseHeadersSize() { + const availableSize = await this._responseHeadersSizePromise; + if (availableSize !== null) + return availableSize; + return responseHeadersSize(await this._rawResponseHeadersPromise, this.statusText()); + } + async internalSizes() { + const requestHeadersSize2 = await this._request._requestHeadersSize(); + const responseHeadersSize2 = await this.responseHeadersSize(); + let encodedBodySize = await this._encodedBodySizePromise; + if (encodedBodySize === null) { + const headers = await this._rawResponseHeadersPromise; + const contentLength = headers.find((h) => h.name.toLowerCase() === "content-length")?.value; + encodedBodySize = contentLength ? +contentLength : 0; + } + let transferSize = await this._transferSizePromise; + if (transferSize === null) { + transferSize = responseHeadersSize2 + encodedBodySize; + } + return { + requestBodySize: this._request.bodySize(), + requestHeadersSize: requestHeadersSize2, + responseBodySize: encodedBodySize, + responseHeadersSize: responseHeadersSize2, + transferSize + }; + } + }; + WebSocket = class _WebSocket extends SdkObject { + constructor(parent, url2) { + super(parent, "ws"); + this._notified = false; + this._url = stripFragmentFromUrl(url2); + } + static { + this.Events = { + Close: "close", + SocketError: "socketerror", + FrameReceived: "framereceived", + FrameSent: "framesent", + Request: "request", + Response: "response" + }; + } + markAsNotified() { + if (this._notified) + return false; + this._notified = true; + return true; + } + url() { + return this._url; + } + wallTimeMs() { + return this._wallTimeMs; + } + setWallTimeMs(wallTimeMs) { + this._wallTimeMs = wallTimeMs; + } + requestSent(headers) { + this.emit(_WebSocket.Events.Request, { headers }); + } + responseReceived(status, statusText2, headers) { + this.emit(_WebSocket.Events.Response, { status, statusText: statusText2, headers }); + } + frameSent(opcode, data, wallTimeMs) { + this.emit(_WebSocket.Events.FrameSent, { opcode, data, wallTimeMs }); + } + frameReceived(opcode, data, wallTimeMs) { + this.emit(_WebSocket.Events.FrameReceived, { opcode, data, wallTimeMs }); + } + error(errorMessage) { + this.emit(_WebSocket.Events.SocketError, errorMessage); + } + closed() { + this.emit(_WebSocket.Events.Close); + } + }; + STATUS_TEXTS = { + "100": "Continue", + "101": "Switching Protocols", + "102": "Processing", + "103": "Early Hints", + "200": "OK", + "201": "Created", + "202": "Accepted", + "203": "Non-Authoritative Information", + "204": "No Content", + "205": "Reset Content", + "206": "Partial Content", + "207": "Multi-Status", + "208": "Already Reported", + "226": "IM Used", + "300": "Multiple Choices", + "301": "Moved Permanently", + "302": "Found", + "303": "See Other", + "304": "Not Modified", + "305": "Use Proxy", + "306": "Switch Proxy", + "307": "Temporary Redirect", + "308": "Permanent Redirect", + "400": "Bad Request", + "401": "Unauthorized", + "402": "Payment Required", + "403": "Forbidden", + "404": "Not Found", + "405": "Method Not Allowed", + "406": "Not Acceptable", + "407": "Proxy Authentication Required", + "408": "Request Timeout", + "409": "Conflict", + "410": "Gone", + "411": "Length Required", + "412": "Precondition Failed", + "413": "Payload Too Large", + "414": "URI Too Long", + "415": "Unsupported Media Type", + "416": "Range Not Satisfiable", + "417": "Expectation Failed", + "418": "I'm a teapot", + "421": "Misdirected Request", + "422": "Unprocessable Entity", + "423": "Locked", + "424": "Failed Dependency", + "425": "Too Early", + "426": "Upgrade Required", + "428": "Precondition Required", + "429": "Too Many Requests", + "431": "Request Header Fields Too Large", + "451": "Unavailable For Legal Reasons", + "500": "Internal Server Error", + "501": "Not Implemented", + "502": "Bad Gateway", + "503": "Service Unavailable", + "504": "Gateway Timeout", + "505": "HTTP Version Not Supported", + "506": "Variant Also Negotiates", + "507": "Insufficient Storage", + "508": "Loop Detected", + "510": "Not Extended", + "511": "Network Authentication Required" + }; + } +}); + +// packages/playwright-core/src/server/cookieStore.ts +function parseRawCookie(header) { + const pairs = header.split(";").filter((s) => s.trim().length > 0).map((p) => { + let key = ""; + let value3 = ""; + const separatorPos = p.indexOf("="); + if (separatorPos === -1) { + key = p.trim(); + } else { + key = p.slice(0, separatorPos).trim(); + value3 = p.slice(separatorPos + 1).trim(); + } + return [key, value3]; + }); + if (!pairs.length) + return null; + const [name, value2] = pairs[0]; + const cookie = { + name, + value: value2 + }; + for (let i = 1; i < pairs.length; i++) { + const [name2, value3] = pairs[i]; + switch (name2.toLowerCase()) { + case "expires": + const expiresMs = +new Date(value3); + if (isFinite(expiresMs)) { + if (expiresMs <= 0) + cookie.expires = 0; + else + cookie.expires = Math.min(expiresMs / 1e3, kMaxCookieExpiresDateInSeconds); + } + break; + case "max-age": + const maxAgeSec = parseInt(value3, 10); + if (isFinite(maxAgeSec)) { + if (maxAgeSec <= 0) + cookie.expires = 0; + else + cookie.expires = Math.min(Date.now() / 1e3 + maxAgeSec, kMaxCookieExpiresDateInSeconds); + } + break; + case "domain": + cookie.domain = value3.toLocaleLowerCase() || ""; + if (cookie.domain && !cookie.domain.startsWith(".") && cookie.domain.includes(".")) + cookie.domain = "." + cookie.domain; + break; + case "path": + cookie.path = value3 || ""; + break; + case "secure": + cookie.secure = true; + break; + case "httponly": + cookie.httpOnly = true; + break; + case "samesite": + switch (value3.toLowerCase()) { + case "none": + cookie.sameSite = "None"; + break; + case "lax": + cookie.sameSite = "Lax"; + break; + case "strict": + cookie.sameSite = "Strict"; + break; + } + break; + } + } + return cookie; +} +function domainMatches(value2, domain) { + if (value2 === domain) + return true; + if (!domain.startsWith(".")) + return false; + value2 = "." + value2; + return value2.endsWith(domain); +} +function pathMatches(value2, path59) { + if (value2 === path59) + return true; + if (!value2.endsWith("/")) + value2 = value2 + "/"; + if (!path59.endsWith("/")) + path59 = path59 + "/"; + return value2.startsWith(path59); +} +var Cookie, CookieStore; +var init_cookieStore = __esm({ + "packages/playwright-core/src/server/cookieStore.ts"() { + "use strict"; + init_network2(); + Cookie = class { + constructor(data) { + this._raw = data; + } + _name() { + return this._raw.name; + } + // https://datatracker.ietf.org/doc/html/rfc6265#section-5.4 + matches(url2) { + if (this._raw.secure && (url2.protocol !== "https:" && !isLocalHostname(url2.hostname))) + return false; + if (!domainMatches(url2.hostname, this._raw.domain)) + return false; + if (!pathMatches(url2.pathname, this._raw.path)) + return false; + return true; + } + _equals(other) { + return this._raw.name === other._raw.name && this._raw.domain === other._raw.domain && this._raw.path === other._raw.path; + } + _networkCookie() { + return this._raw; + } + _updateExpiresFrom(other) { + this._raw.expires = other._raw.expires; + } + _expired() { + if (this._raw.expires === -1) + return false; + return this._raw.expires * 1e3 < Date.now(); + } + }; + CookieStore = class _CookieStore { + constructor() { + this._nameToCookies = /* @__PURE__ */ new Map(); + } + addCookies(cookies) { + for (const cookie of cookies) + this._addCookie(new Cookie(cookie)); + } + cookies(url2) { + const result2 = []; + for (const cookie of this._cookiesIterator()) { + if (cookie.matches(url2)) + result2.push(cookie._networkCookie()); + } + return result2; + } + allCookies() { + const result2 = []; + for (const cookie of this._cookiesIterator()) + result2.push(cookie._networkCookie()); + return result2; + } + _addCookie(cookie) { + let set = this._nameToCookies.get(cookie._name()); + if (!set) { + set = /* @__PURE__ */ new Set(); + this._nameToCookies.set(cookie._name(), set); + } + for (const other of set) { + if (other._equals(cookie)) + set.delete(other); + } + set.add(cookie); + _CookieStore.pruneExpired(set); + } + *_cookiesIterator() { + for (const [name, cookies] of this._nameToCookies) { + _CookieStore.pruneExpired(cookies); + for (const cookie of cookies) + yield cookie; + if (cookies.size === 0) + this._nameToCookies.delete(name); + } + } + static pruneExpired(cookies) { + for (const cookie of cookies) { + if (cookie._expired()) + cookies.delete(cookie); + } + } + }; + } +}); + +// packages/playwright-core/src/server/formData.ts +function generateUniqueBoundaryString() { + const charCodes = []; + for (let i = 0; i < 16; i++) + charCodes.push(alphaNumericEncodingMap[Math.floor(Math.random() * alphaNumericEncodingMap.length)]); + return "----WebKitFormBoundary" + String.fromCharCode(...charCodes); +} +var mime2, MultipartFormData, alphaNumericEncodingMap; +var init_formData = __esm({ + "packages/playwright-core/src/server/formData.ts"() { + "use strict"; + mime2 = require("./utilsBundle").mime; + MultipartFormData = class { + constructor() { + this._chunks = []; + this._boundary = generateUniqueBoundaryString(); + } + contentTypeHeader() { + return `multipart/form-data; boundary=${this._boundary}`; + } + addField(name, value2) { + this._beginMultiPartHeader(name); + this._finishMultiPartHeader(); + this._chunks.push(Buffer.from(value2)); + this._finishMultiPartField(); + } + addFileField(name, value2) { + this._beginMultiPartHeader(name); + this._chunks.push(Buffer.from(`; filename="${value2.name}"`)); + this._chunks.push(Buffer.from(`\r +content-type: ${value2.mimeType || mime2.getType(value2.name) || "application/octet-stream"}`)); + this._finishMultiPartHeader(); + this._chunks.push(value2.buffer); + this._finishMultiPartField(); + } + finish() { + this._addBoundary(true); + return Buffer.concat(this._chunks); + } + _beginMultiPartHeader(name) { + this._addBoundary(); + this._chunks.push(Buffer.from(`content-disposition: form-data; name="${name}"`)); + } + _finishMultiPartHeader() { + this._chunks.push(Buffer.from(`\r +\r +`)); + } + _finishMultiPartField() { + this._chunks.push(Buffer.from(`\r +`)); + } + _addBoundary(isLastBoundary) { + this._chunks.push(Buffer.from("--" + this._boundary)); + if (isLastBoundary) + this._chunks.push(Buffer.from("--")); + this._chunks.push(Buffer.from("\r\n")); + } + }; + alphaNumericEncodingMap = [ + 65, + 66, + 67, + 68, + 69, + 70, + 71, + 72, + 73, + 74, + 75, + 76, + 77, + 78, + 79, + 80, + 81, + 82, + 83, + 84, + 85, + 86, + 87, + 88, + 89, + 90, + 97, + 98, + 99, + 100, + 101, + 102, + 103, + 104, + 105, + 106, + 107, + 108, + 109, + 110, + 111, + 112, + 113, + 114, + 115, + 116, + 117, + 118, + 119, + 120, + 121, + 122, + 48, + 49, + 50, + 51, + 52, + 53, + 54, + 55, + 56, + 57, + 65, + 66 + ]; + } +}); + +// packages/playwright-core/src/server/socksClientCertificatesInterceptor.ts +function loadDummyServerCertsIfNeeded() { + if (dummyServerTlsOptions) + return; + const { cert, key } = generateSelfSignedCertificate(); + dummyServerTlsOptions = { key, cert }; +} +function normalizeOrigin(origin) { + try { + return new URL(origin).origin; + } catch (error) { + return origin; + } +} +function convertClientCertificatesToTLSOptions(clientCertificates) { + if (!clientCertificates || !clientCertificates.length) + return; + const tlsOptions = { + pfx: [], + key: [], + cert: [] + }; + for (const cert of clientCertificates) { + if (cert.cert) + tlsOptions.cert.push(cert.cert); + if (cert.key) + tlsOptions.key.push({ pem: cert.key, passphrase: cert.passphrase }); + if (cert.pfx) + tlsOptions.pfx.push({ buf: cert.pfx, passphrase: cert.passphrase }); + } + return tlsOptions; +} +function getMatchingTLSOptionsForOrigin(clientCertificates, origin) { + const matchingCerts = clientCertificates?.filter( + (c) => normalizeOrigin(c.origin) === origin + ); + return convertClientCertificatesToTLSOptions(matchingCerts); +} +function rewriteToLocalhostIfNeeded(host) { + return host === "local.playwright" ? "localhost" : host; +} +function rewriteOpenSSLErrorIfNeeded(error) { + if (error.message !== "unsupported" && error.code !== "ERR_CRYPTO_UNSUPPORTED_OPERATION") + return error; + return rewriteErrorMessage(error, [ + "Unsupported TLS certificate.", + "Most likely, the security algorithm of the given certificate was deprecated by OpenSSL.", + "For more details, see https://github.com/openssl/openssl/blob/master/README-PROVIDERS.md#the-legacy-provider", + "You could probably modernize the certificate by following the steps at https://github.com/nodejs/node/issues/40672#issuecomment-1243648223" + ].join("\n")); +} +function parseALPNFromClientHello(buffer) { + if (buffer.length < 6) + return null; + if (buffer[0] !== 22) + return null; + let offset = 5; + if (buffer[offset] !== 1) + return null; + offset += 4; + offset += 2; + offset += 32; + if (offset >= buffer.length) + return null; + const sessionIdLength = buffer[offset]; + offset += 1 + sessionIdLength; + if (offset + 2 > buffer.length) + return null; + const cipherSuitesLength = buffer.readUInt16BE(offset); + offset += 2 + cipherSuitesLength; + if (offset >= buffer.length) + return null; + const compressionMethodsLength = buffer[offset]; + offset += 1 + compressionMethodsLength; + if (offset + 2 > buffer.length) + return null; + const extensionsLength = buffer.readUInt16BE(offset); + offset += 2; + const extensionsEnd = offset + extensionsLength; + if (extensionsEnd > buffer.length) + return null; + while (offset + 4 <= extensionsEnd) { + const extensionType = buffer.readUInt16BE(offset); + offset += 2; + const extensionLength = buffer.readUInt16BE(offset); + offset += 2; + if (offset + extensionLength > extensionsEnd) + return null; + if (extensionType === 16) + return parseALPNExtension(buffer.subarray(offset, offset + extensionLength)); + offset += extensionLength; + } + return null; +} +function parseALPNExtension(buffer) { + if (buffer.length < 2) + return null; + const listLength = buffer.readUInt16BE(0); + if (listLength !== buffer.length - 2) + return null; + const protocols = []; + let offset = 2; + while (offset < buffer.length) { + const protocolLength = buffer[offset]; + offset += 1; + if (offset + protocolLength > buffer.length) + break; + const protocol = buffer.subarray(offset, offset + protocolLength).toString("utf8"); + protocols.push(protocol); + offset += protocolLength; + } + return protocols.length > 0 ? protocols : null; +} +var import_events4, import_http23, import_net3, import_stream3, import_tls2, getProxyForUrl2, dummyServerTlsOptions, SocksProxyConnection, ClientCertificatesProxy; +var init_socksClientCertificatesInterceptor = __esm({ + "packages/playwright-core/src/server/socksClientCertificatesInterceptor.ts"() { + "use strict"; + import_events4 = require("events"); + import_http23 = __toESM(require("http2")); + import_net3 = __toESM(require("net")); + import_stream3 = __toESM(require("stream")); + import_tls2 = __toESM(require("tls")); + init_socksProxy(); + init_debugLogger(); + init_happyEyeballs(); + init_stringUtils(); + init_crypto(); + init_stackTrace(); + init_network(); + init_browserContext(); + ({ getProxyForUrl: getProxyForUrl2 } = require("./utilsBundle")); + dummyServerTlsOptions = void 0; + SocksProxyConnection = class { + constructor(socksProxy, uid, host, port) { + this._firstPackageReceived = false; + this._closed = false; + this.socksProxy = socksProxy; + this.uid = uid; + this.host = host; + this.port = port; + this._serverCloseEventListener = () => { + this._browserEncrypted.destroy(); + }; + this._browserEncrypted = new import_stream3.default.Duplex({ + read: () => { + }, + write: (data, encoding, callback) => { + this.socksProxy._socksProxy.sendSocketData({ uid: this.uid, data }); + callback(); + }, + destroy: (error, callback) => { + if (error) + socksProxy._socksProxy.sendSocketError({ uid: this.uid, error: error.message }); + else + socksProxy._socksProxy.sendSocketEnd({ uid: this.uid }); + callback(); + } + }); + } + async connect() { + const proxyAgent = this.socksProxy._getProxyAgent(this.host, this.port); + if (proxyAgent) + this._serverEncrypted = await proxyAgent.connect(new import_events4.EventEmitter(), { host: rewriteToLocalhostIfNeeded(this.host), port: this.port, secureEndpoint: false }); + else + this._serverEncrypted = await createSocket(rewriteToLocalhostIfNeeded(this.host), this.port); + this._serverEncrypted.once("close", this._serverCloseEventListener); + this._serverEncrypted.once("error", (error) => this._browserEncrypted.destroy(error)); + if (this._closed) { + this._serverEncrypted.destroy(); + return; + } + this.socksProxy._socksProxy.socketConnected({ + uid: this.uid, + host: this._serverEncrypted.localAddress, + port: this._serverEncrypted.localPort + }); + } + onClose() { + this._serverEncrypted.destroy(); + this._browserEncrypted.destroy(); + this._closed = true; + } + onData(data) { + if (!this._firstPackageReceived) { + this._firstPackageReceived = true; + const secureContext = data[0] === 22 ? this.socksProxy.secureContextMap.get(normalizeOrigin(`https://${this.host}:${this.port}`)) : void 0; + if (secureContext) + this._establishTlsTunnel(this._browserEncrypted, data, secureContext); + else + this._establishPlaintextTunnel(this._browserEncrypted); + } + this._browserEncrypted.push(data); + } + _establishPlaintextTunnel(browserEncrypted) { + browserEncrypted.pipe(this._serverEncrypted); + this._serverEncrypted.pipe(browserEncrypted); + } + _establishTlsTunnel(browserEncrypted, clientHello, secureContext) { + const browserALPNProtocols = parseALPNFromClientHello(clientHello) || ["http/1.1"]; + debugLogger.log("client-certificates", `Browser->Proxy ${this.host}:${this.port} offers ALPN ${browserALPNProtocols}`); + const rejectUnauthorized = !this.socksProxy.ignoreHTTPSErrors; + const serverDecrypted = import_tls2.default.connect({ + socket: this._serverEncrypted, + host: this.host, + port: this.port, + rejectUnauthorized, + ALPNProtocols: browserALPNProtocols, + servername: !import_net3.default.isIP(this.host) ? this.host : void 0, + secureContext + }, async () => { + const browserDecrypted = await this._upgradeToTLSIfNeeded(browserEncrypted, serverDecrypted.alpnProtocol); + debugLogger.log("client-certificates", `Proxy->Server ${this.host}:${this.port} chooses ALPN ${browserDecrypted.alpnProtocol}`); + browserDecrypted.pipe(serverDecrypted); + serverDecrypted.pipe(browserDecrypted); + const cleanup = (error) => this._serverEncrypted.destroy(error); + browserDecrypted.once("error", cleanup); + serverDecrypted.once("error", cleanup); + browserDecrypted.once("close", cleanup); + serverDecrypted.once("close", cleanup); + if (this._closed) + serverDecrypted.destroy(); + }); + serverDecrypted.once("error", async (error) => { + debugLogger.log("client-certificates", `error when connecting to server: ${error.message.replaceAll("\n", " ")}`); + this._serverEncrypted.removeListener("close", this._serverCloseEventListener); + this._serverEncrypted.destroy(); + const browserDecrypted = await this._upgradeToTLSIfNeeded(this._browserEncrypted, serverDecrypted.alpnProtocol); + const responseBody = escapeHTML("Playwright client-certificate error: " + error.message).replaceAll("\n", "
"); + if (browserDecrypted.alpnProtocol === "h2") { + if ("performServerHandshake" in import_http23.default) { + const session2 = import_http23.default.performServerHandshake(browserDecrypted); + session2.on("error", (error2) => { + this._browserEncrypted.destroy(error2); + }); + session2.once("stream", (stream3) => { + const cleanup = (error2) => { + session2.close(); + this._browserEncrypted.destroy(error2); + }; + stream3.once("end", cleanup); + stream3.once("error", cleanup); + stream3.respond({ + [import_http23.default.constants.HTTP2_HEADER_CONTENT_TYPE]: "text/html", + [import_http23.default.constants.HTTP2_HEADER_STATUS]: 503 + }); + stream3.end(responseBody); + }); + } else { + this._browserEncrypted.destroy(error); + } + } else { + browserDecrypted.end([ + "HTTP/1.1 503 Internal Server Error", + "Content-Type: text/html; charset=utf-8", + "Content-Length: " + Buffer.byteLength(responseBody), + "", + responseBody + ].join("\r\n")); + } + }); + } + async _upgradeToTLSIfNeeded(socket, alpnProtocol) { + this._brorwserDecrypted ??= new Promise((resolve, reject) => { + const dummyServer = import_tls2.default.createServer({ + ...dummyServerTlsOptions, + ALPNProtocols: [alpnProtocol || "http/1.1"] + }); + dummyServer.emit("connection", socket); + dummyServer.once("secureConnection", (tlsSocket) => { + dummyServer.close(); + resolve(tlsSocket); + }); + dummyServer.once("error", (error) => { + dummyServer.close(); + reject(error); + }); + }); + return this._brorwserDecrypted; + } + }; + ClientCertificatesProxy = class _ClientCertificatesProxy { + constructor(contextOptions) { + this._connections = /* @__PURE__ */ new Map(); + this.secureContextMap = /* @__PURE__ */ new Map(); + verifyClientCertificates(contextOptions.clientCertificates); + this.ignoreHTTPSErrors = contextOptions.ignoreHTTPSErrors; + this._proxy = contextOptions.proxy; + this._initSecureContexts(contextOptions.clientCertificates); + this._socksProxy = new SocksProxy(); + this._socksProxy.setPattern("*"); + this._socksProxy.addListener(SocksProxy.Events.SocksRequested, async (payload) => { + try { + const connection = new SocksProxyConnection(this, payload.uid, payload.host, payload.port); + await connection.connect(); + this._connections.set(payload.uid, connection); + } catch (error) { + debugLogger.log("client-certificates", `Failed to connect to ${payload.host}:${payload.port}: ${error.message}`); + this._socksProxy.socketFailed({ uid: payload.uid, errorCode: error.code }); + } + }); + this._socksProxy.addListener(SocksProxy.Events.SocksData, (payload) => { + this._connections.get(payload.uid)?.onData(payload.data); + }); + this._socksProxy.addListener(SocksProxy.Events.SocksClosed, (payload) => { + this._connections.get(payload.uid)?.onClose(); + this._connections.delete(payload.uid); + }); + loadDummyServerCertsIfNeeded(); + } + _getProxyAgent(host, port) { + const proxyFromOptions = createProxyAgent(this._proxy); + if (proxyFromOptions) + return proxyFromOptions; + const proxyFromEnv = getProxyForUrl2(`https://${host}:${port}`); + if (proxyFromEnv) + return createProxyAgent({ server: proxyFromEnv }); + } + _initSecureContexts(clientCertificates) { + const origin2certs = /* @__PURE__ */ new Map(); + for (const cert of clientCertificates || []) { + const origin = normalizeOrigin(cert.origin); + const certs = origin2certs.get(origin) || []; + certs.push(cert); + origin2certs.set(origin, certs); + } + for (const [origin, certs] of origin2certs) { + try { + this.secureContextMap.set(origin, import_tls2.default.createSecureContext(convertClientCertificatesToTLSOptions(certs))); + } catch (error) { + error = rewriteOpenSSLErrorIfNeeded(error); + throw rewriteErrorMessage(error, `Failed to load client certificate: ${error.message}`); + } + } + } + static async create(progress2, contextOptions) { + const proxy = new _ClientCertificatesProxy(contextOptions); + try { + await progress2.race(proxy._socksProxy.listen(0, "127.0.0.1")); + return proxy; + } catch (error) { + await progress2.race(proxy.close()); + throw error; + } + } + proxySettings() { + return { server: `socks5://127.0.0.1:${this._socksProxy.port()}` }; + } + async close() { + await this._socksProxy.close(); + } + }; + } +}); + +// packages/playwright-core/src/server/trace/recorder/snapshotterInjected.ts +function frameSnapshotStreamer(snapshotStreamer, removeNoScript) { + if (window[snapshotStreamer]) + return; + const kShadowAttribute = "__playwright_shadow_root_"; + const kValueAttribute = "__playwright_value_"; + const kCheckedAttribute = "__playwright_checked_"; + const kSelectedAttribute = "__playwright_selected_"; + const kScrollTopAttribute = "__playwright_scroll_top_"; + const kScrollLeftAttribute = "__playwright_scroll_left_"; + const kStyleSheetAttribute = "__playwright_style_sheet_"; + const kTargetAttribute = "__playwright_target__"; + const kCustomElementsAttribute = "__playwright_custom_elements__"; + const kCurrentSrcAttribute = "__playwright_current_src__"; + const kBoundingRectAttribute = "__playwright_bounding_rect__"; + const kPopoverOpenAttribute = "__playwright_popover_open_"; + const kDialogOpenAttribute = "__playwright_dialog_open_"; + const kSnapshotFrameId = Symbol("__playwright_snapshot_frameid_"); + const kCachedData = Symbol("__playwright_snapshot_cache_"); + const kEndOfList = Symbol("__playwright_end_of_list_"); + function resetCachedData(obj) { + delete obj[kCachedData]; + } + function ensureCachedData(obj) { + if (!obj[kCachedData]) + obj[kCachedData] = {}; + return obj[kCachedData]; + } + const kObserverConfig = { attributes: true, subtree: true }; + function removeHash2(url2) { + try { + const u = new URL(url2); + u.hash = ""; + return u.toString(); + } catch (e) { + return url2; + } + } + class Streamer { + constructor() { + this._lastSnapshotNumber = 0; + this._staleStyleSheets = /* @__PURE__ */ new Set(); + this._modifiedStyleSheets = /* @__PURE__ */ new Set(); + this._readingStyleSheet = false; + this._targetGeneration = 0; + const invalidateCSSGroupingRule = (rule) => { + if (rule.parentStyleSheet) + this._invalidateStyleSheet(rule.parentStyleSheet); + }; + this._interceptNativeMethod(window.CSSStyleSheet.prototype, "insertRule", (sheet) => this._invalidateStyleSheet(sheet)); + this._interceptNativeMethod(window.CSSStyleSheet.prototype, "deleteRule", (sheet) => this._invalidateStyleSheet(sheet)); + this._interceptNativeMethod(window.CSSStyleSheet.prototype, "addRule", (sheet) => this._invalidateStyleSheet(sheet)); + this._interceptNativeMethod(window.CSSStyleSheet.prototype, "removeRule", (sheet) => this._invalidateStyleSheet(sheet)); + this._interceptNativeGetter(window.CSSStyleSheet.prototype, "rules", (sheet) => this._invalidateStyleSheet(sheet)); + this._interceptNativeGetter(window.CSSStyleSheet.prototype, "cssRules", (sheet) => this._invalidateStyleSheet(sheet)); + this._interceptNativeMethod(window.CSSStyleSheet.prototype, "replaceSync", (sheet) => this._invalidateStyleSheet(sheet)); + this._interceptNativeMethod(window.CSSGroupingRule.prototype, "insertRule", invalidateCSSGroupingRule); + this._interceptNativeMethod(window.CSSGroupingRule.prototype, "deleteRule", invalidateCSSGroupingRule); + this._interceptNativeGetter(window.CSSGroupingRule.prototype, "cssRules", invalidateCSSGroupingRule); + this._interceptNativeSetter(window.StyleSheet.prototype, "disabled", (sheet) => { + if (sheet instanceof CSSStyleSheet) + this._invalidateStyleSheet(sheet); + }); + this._interceptNativeAsyncMethod(window.CSSStyleSheet.prototype, "replace", (sheet) => this._invalidateStyleSheet(sheet)); + this._fakeBase = document.createElement("base"); + this._observer = new MutationObserver((list) => this._handleMutations(list)); + this._ensureObservingCurrentDocument(); + } + _refreshListenersWhenNeeded() { + this._refreshListeners(); + const customEventName = "__playwright_snapshotter_global_listeners_check__"; + let seenEvent = false; + const handleCustomEvent = () => seenEvent = true; + window.addEventListener(customEventName, handleCustomEvent); + const observer = new MutationObserver((entries) => { + const newDocumentElement = entries.some((entry) => Array.from(entry.addedNodes).includes(document.documentElement)); + if (newDocumentElement) { + seenEvent = false; + window.dispatchEvent(new CustomEvent(customEventName)); + if (!seenEvent) { + window.addEventListener(customEventName, handleCustomEvent); + this._refreshListeners(); + } + } + }); + observer.observe(document, { childList: true }); + } + _refreshListeners() { + document.addEventListener("__playwright_mark_target__", (event) => { + const target = event.composedPath()[0]; + if (target?.nodeType !== Node.ELEMENT_NODE) + return; + target.__playwright_target__ = this._targetGeneration; + }); + document.addEventListener("__playwright_reset_targets__", () => { + ++this._targetGeneration; + }); + } + _interceptNativeMethod(obj, method, cb) { + const native = obj[method]; + if (!native) + return; + obj[method] = function(...args) { + const result2 = native.call(this, ...args); + cb(this, result2); + return result2; + }; + } + _interceptNativeAsyncMethod(obj, method, cb) { + const native = obj[method]; + if (!native) + return; + obj[method] = async function(...args) { + const result2 = await native.call(this, ...args); + cb(this, result2); + return result2; + }; + } + _interceptNativeGetter(obj, prop, cb) { + const descriptor = Object.getOwnPropertyDescriptor(obj, prop); + Object.defineProperty(obj, prop, { + ...descriptor, + get: function() { + const result2 = descriptor.get.call(this); + cb(this, result2); + return result2; + } + }); + } + _interceptNativeSetter(obj, prop, cb) { + const descriptor = Object.getOwnPropertyDescriptor(obj, prop); + Object.defineProperty(obj, prop, { + ...descriptor, + set: function(value2) { + const result2 = descriptor.set.call(this, value2); + cb(this, value2); + return result2; + } + }); + } + _handleMutations(list) { + for (const mutation of list) + ensureCachedData(mutation.target).attributesCached = void 0; + } + _ensureObservingCurrentDocument() { + if (this._observedDocument === document) + return; + this._observedDocument = document; + this._observer.disconnect(); + this._observer.observe(document, kObserverConfig); + this._refreshListenersWhenNeeded(); + } + _invalidateStyleSheet(sheet) { + if (this._readingStyleSheet) + return; + this._staleStyleSheets.add(sheet); + if (sheet.href !== null) + this._modifiedStyleSheets.add(sheet); + } + _updateStyleElementStyleSheetTextIfNeeded(sheet, forceText) { + const data = ensureCachedData(sheet); + if (this._staleStyleSheets.has(sheet) || forceText && data.cssText === void 0) { + this._staleStyleSheets.delete(sheet); + try { + data.cssText = this._getSheetText(sheet); + } catch (e) { + data.cssText = ""; + } + } + return data.cssText; + } + // Returns either content, ref, or no override. + _updateLinkStyleSheetTextIfNeeded(sheet, snapshotNumber) { + const data = ensureCachedData(sheet); + if (this._staleStyleSheets.has(sheet)) { + this._staleStyleSheets.delete(sheet); + try { + data.cssText = this._getSheetText(sheet); + data.cssRef = snapshotNumber; + return data.cssText; + } catch (e) { + } + } + return data.cssRef === void 0 ? void 0 : snapshotNumber - data.cssRef; + } + markIframe(iframeElement, frameId) { + iframeElement[kSnapshotFrameId] = frameId; + } + resetHistory() { + this._staleStyleSheets.clear(); + const visitNode = (node) => { + resetCachedData(node); + if (node.nodeType === Node.ELEMENT_NODE) { + const element2 = node; + if (element2.shadowRoot) + visitNode(element2.shadowRoot); + } + for (let child = node.firstChild; child; child = child.nextSibling) + visitNode(child); + }; + visitNode(document.documentElement); + visitNode(this._fakeBase); + } + __sanitizeMetaAttribute(name, value2, httpEquiv) { + if (name === "charset") + return "utf-8"; + if (httpEquiv.toLowerCase() !== "content-type" || name !== "content") + return value2; + const [type3, ...params2] = value2.split(";"); + if (type3 !== "text/html" || params2.length <= 0) + return value2; + const charsetParamIdx = params2.findIndex((param) => param.trim().startsWith("charset=")); + if (charsetParamIdx > -1) + params2[charsetParamIdx] = "charset=utf-8"; + return `${type3}; ${params2.join("; ")}`; + } + _sanitizeUrl(url2) { + if (url2.startsWith("javascript:") || url2.startsWith("vbscript:")) + return ""; + return url2; + } + _sanitizeSrcSet(srcset) { + return srcset.split(",").map((src) => { + src = src.trim(); + const spaceIndex = src.lastIndexOf(" "); + if (spaceIndex === -1) + return this._sanitizeUrl(src); + return this._sanitizeUrl(src.substring(0, spaceIndex).trim()) + src.substring(spaceIndex); + }).join(", "); + } + _resolveUrl(base, url2) { + if (url2 === "") + return ""; + try { + return new URL(url2, base).href; + } catch (e) { + return url2; + } + } + _getSheetBase(sheet) { + let rootSheet = sheet; + while (rootSheet.parentStyleSheet) + rootSheet = rootSheet.parentStyleSheet; + if (rootSheet.ownerNode) + return rootSheet.ownerNode.baseURI; + return document.baseURI; + } + _getSheetText(sheet) { + this._readingStyleSheet = true; + try { + if (sheet.disabled) + return ""; + const rules = []; + for (const rule of sheet.cssRules) + rules.push(rule.cssText); + return rules.join("\n"); + } finally { + this._readingStyleSheet = false; + } + } + captureSnapshot(reset) { + const timestamp = performance.now(); + const snapshotNumber = ++this._lastSnapshotNumber; + if (reset === "history") + this.resetHistory(); + if (reset) + ++this._targetGeneration; + let nodeCounter = 0; + let shadowDomNesting = 0; + let headNesting = 0; + this._ensureObservingCurrentDocument(); + this._handleMutations(this._observer.takeRecords()); + const definedCustomElements = /* @__PURE__ */ new Set(); + const visitNode = (node) => { + const nodeType = node.nodeType; + const nodeName = nodeType === Node.DOCUMENT_FRAGMENT_NODE ? "template" : node.nodeName; + if (nodeType !== Node.ELEMENT_NODE && nodeType !== Node.DOCUMENT_FRAGMENT_NODE && nodeType !== Node.TEXT_NODE) + return; + if (nodeName === "SCRIPT") + return; + if (nodeName === "LINK" && nodeType === Node.ELEMENT_NODE) { + const rel = node.getAttribute("rel")?.toLowerCase(); + if (rel === "preload" || rel === "prefetch") + return; + } + if (removeNoScript && nodeName === "NOSCRIPT") + return; + if (nodeName === "META") { + const httpEquiv = node.httpEquiv.toLowerCase(); + if (httpEquiv === "content-security-policy" || httpEquiv === "refresh" || httpEquiv === "set-cookie") + return; + } + if ((nodeName === "IFRAME" || nodeName === "FRAME") && headNesting) + return; + const data = ensureCachedData(node); + const values = []; + let equals = !!data.cached; + let extraNodes = 0; + const expectValue = (value2) => { + equals = equals && data.cached[values.length] === value2; + values.push(value2); + }; + const checkAndReturn = (n) => { + data.attributesCached = true; + if (equals) + return { equals: true, n: [[snapshotNumber - data.ref[0], data.ref[1]]] }; + nodeCounter += extraNodes; + data.ref = [snapshotNumber, nodeCounter++]; + data.cached = values; + return { equals: false, n }; + }; + if (nodeType === Node.TEXT_NODE) { + const value2 = node.nodeValue || ""; + expectValue(value2); + return checkAndReturn(value2); + } + if (nodeName === "STYLE") { + const sheet = node.sheet; + let cssText; + if (sheet) + cssText = this._updateStyleElementStyleSheetTextIfNeeded(sheet); + cssText = cssText || node.textContent || ""; + expectValue(cssText); + extraNodes++; + return checkAndReturn([nodeName, {}, cssText]); + } + const attrs = {}; + const result3 = [nodeName, attrs]; + const visitChild = (child) => { + const snapshot3 = visitNode(child); + if (snapshot3) { + result3.push(snapshot3.n); + expectValue(child); + equals = equals && snapshot3.equals; + } + }; + const visitChildStyleSheet = (child) => { + const snapshot3 = visitStyleSheet(child); + if (snapshot3) { + result3.push(snapshot3.n); + expectValue(child); + equals = equals && snapshot3.equals; + } + }; + if (nodeType === Node.DOCUMENT_FRAGMENT_NODE) + attrs[kShadowAttribute] = "open"; + if (nodeType === Node.ELEMENT_NODE) { + const element2 = node; + if (element2.localName.includes("-") && window.customElements?.get(element2.localName)) + definedCustomElements.add(element2.localName); + if (nodeName === "INPUT" || nodeName === "TEXTAREA") { + const value2 = element2.value; + expectValue(kValueAttribute); + expectValue(value2); + attrs[kValueAttribute] = value2; + } + if (nodeName === "INPUT" && ["checkbox", "radio"].includes(element2.type)) { + const value2 = element2.checked ? "true" : "false"; + expectValue(kCheckedAttribute); + expectValue(value2); + attrs[kCheckedAttribute] = value2; + } + if (nodeName === "OPTION") { + const value2 = element2.selected ? "true" : "false"; + expectValue(kSelectedAttribute); + expectValue(value2); + attrs[kSelectedAttribute] = value2; + } + if (nodeName === "CANVAS" || nodeName === "IFRAME" || nodeName === "FRAME") { + const boundingRect = element2.getBoundingClientRect(); + const value2 = JSON.stringify({ + left: boundingRect.left, + top: boundingRect.top, + right: boundingRect.right, + bottom: boundingRect.bottom + }); + expectValue(kBoundingRectAttribute); + expectValue(value2); + attrs[kBoundingRectAttribute] = value2; + } + if (element2.popover && element2.matches && element2.matches(":popover-open")) { + const value2 = "true"; + expectValue(kPopoverOpenAttribute); + expectValue(value2); + attrs[kPopoverOpenAttribute] = value2; + } + if (nodeName === "DIALOG" && element2.open) { + const value2 = element2.matches(":modal") ? "modal" : "true"; + expectValue(kDialogOpenAttribute); + expectValue(value2); + attrs[kDialogOpenAttribute] = value2; + } + if (element2.scrollTop) { + expectValue(kScrollTopAttribute); + expectValue(element2.scrollTop); + attrs[kScrollTopAttribute] = "" + element2.scrollTop; + } + if (element2.scrollLeft) { + expectValue(kScrollLeftAttribute); + expectValue(element2.scrollLeft); + attrs[kScrollLeftAttribute] = "" + element2.scrollLeft; + } + if (element2.shadowRoot) { + ++shadowDomNesting; + visitChild(element2.shadowRoot); + --shadowDomNesting; + } + if (element2.__playwright_target__ === this._targetGeneration) { + expectValue(kTargetAttribute); + attrs[kTargetAttribute] = ""; + } + } + if (nodeName === "HEAD") { + ++headNesting; + this._fakeBase.setAttribute("href", document.baseURI); + visitChild(this._fakeBase); + } + for (let child = node.firstChild; child; child = child.nextSibling) + visitChild(child); + if (nodeName === "HEAD") + --headNesting; + expectValue(kEndOfList); + let documentOrShadowRoot = null; + if (node.ownerDocument.documentElement === node) + documentOrShadowRoot = node.ownerDocument; + else if (node.nodeType === Node.DOCUMENT_FRAGMENT_NODE) + documentOrShadowRoot = node; + if (documentOrShadowRoot) { + for (const sheet of documentOrShadowRoot.adoptedStyleSheets || []) + visitChildStyleSheet(sheet); + expectValue(kEndOfList); + } + if (nodeName === "IFRAME" || nodeName === "FRAME") { + const element2 = node; + const frameId = element2[kSnapshotFrameId]; + const name = "src"; + const value2 = frameId ? `/snapshot/${frameId}` : ""; + expectValue(name); + expectValue(value2); + attrs[name] = value2; + } + if (nodeName === "BODY" && definedCustomElements.size) { + const value2 = [...definedCustomElements].join(","); + expectValue(kCustomElementsAttribute); + expectValue(value2); + attrs[kCustomElementsAttribute] = value2; + } + if (nodeName === "IMG" || nodeName === "PICTURE") { + const value2 = nodeName === "PICTURE" ? "" : this._sanitizeUrl(node.currentSrc); + expectValue(kCurrentSrcAttribute); + expectValue(value2); + attrs[kCurrentSrcAttribute] = value2; + } + if (equals && data.attributesCached && !shadowDomNesting) + return checkAndReturn(result3); + if (nodeType === Node.ELEMENT_NODE) { + const element2 = node; + for (let i = 0; i < element2.attributes.length; i++) { + const name = element2.attributes[i].name; + if (nodeName === "LINK" && name === "integrity") + continue; + if (nodeName === "IFRAME" && (name === "src" || name === "srcdoc" || name === "sandbox")) + continue; + if (nodeName === "FRAME" && name === "src") + continue; + if (nodeName === "DIALOG" && name === "open") + continue; + let value2 = element2.attributes[i].value; + if (nodeName === "META") + value2 = this.__sanitizeMetaAttribute(name, value2, node.httpEquiv); + else if (name === "src" && nodeName === "IMG") + value2 = this._sanitizeUrl(value2); + else if (name === "srcset" && nodeName === "IMG") + value2 = this._sanitizeSrcSet(value2); + else if (name === "srcset" && nodeName === "SOURCE") + value2 = this._sanitizeSrcSet(value2); + else if (name === "href" && nodeName === "LINK") + value2 = this._sanitizeUrl(value2); + else if (name.startsWith("on")) + value2 = ""; + expectValue(name); + expectValue(value2); + attrs[name] = value2; + } + expectValue(kEndOfList); + } + if (result3.length === 2 && !Object.keys(attrs).length) + result3.pop(); + return checkAndReturn(result3); + }; + const visitStyleSheet = (sheet) => { + const data = ensureCachedData(sheet); + const oldCSSText = data.cssText; + const cssText = this._updateStyleElementStyleSheetTextIfNeeded( + sheet, + true + /* forceText */ + ); + if (cssText === oldCSSText) + return { equals: true, n: [[snapshotNumber - data.ref[0], data.ref[1]]] }; + data.ref = [snapshotNumber, nodeCounter++]; + return { + equals: false, + n: ["template", { + [kStyleSheetAttribute]: cssText + }] + }; + }; + let html; + if (document.documentElement) { + const { n } = visitNode(document.documentElement); + html = n; + } else { + html = ["html"]; + } + const result2 = { + html, + doctype: document.doctype ? document.doctype.name : void 0, + resourceOverrides: [], + viewport: { + width: window.innerWidth, + height: window.innerHeight + }, + url: location.href, + wallTime: Date.now(), + collectionTime: 0 + }; + for (const sheet of this._modifiedStyleSheets) { + if (sheet.href === null) + continue; + const content = this._updateLinkStyleSheetTextIfNeeded(sheet, snapshotNumber); + if (content === void 0) { + continue; + } + const base = this._getSheetBase(sheet); + const url2 = removeHash2(this._resolveUrl(base, sheet.href)); + result2.resourceOverrides.push({ url: url2, content, contentType: "text/css" }); + } + result2.collectionTime = performance.now() - timestamp; + return result2; + } + } + window[snapshotStreamer] = new Streamer(); +} +var init_snapshotterInjected = __esm({ + "packages/playwright-core/src/server/trace/recorder/snapshotterInjected.ts"() { + "use strict"; + } +}); + +// packages/playwright-core/src/server/trace/recorder/snapshotter.ts +var mime3, Snapshotter, kNeedsResetSymbol; +var init_snapshotter = __esm({ + "packages/playwright-core/src/server/trace/recorder/snapshotter.ts"() { + "use strict"; + init_time(); + init_crypto(); + init_debugLogger(); + init_eventsHelper(); + init_snapshotterInjected(); + init_browserContext(); + init_progress(); + mime3 = require("./utilsBundle").mime; + Snapshotter = class { + constructor(context2, delegate) { + this._eventListeners = []; + this._started = false; + this._context = context2; + this._delegate = delegate; + const guid = createGuid(); + this._snapshotStreamer = "__playwright_snapshot_streamer_" + guid; + } + started() { + return this._started; + } + async start(progress2) { + this._started = true; + if (!this._initScript) + await this._initialize(progress2); + await progress2.race(this.reset()); + } + async reset() { + if (this._started) + await this._context.safeNonStallingEvaluateInAllFrames(`window["${this._snapshotStreamer}"].resetHistory()`, "main"); + } + stop() { + this._started = false; + } + async resetForReuse() { + if (this._initScript) { + eventsHelper.removeEventListeners(this._eventListeners); + await this._initScript.dispose(); + this._initScript = void 0; + } + } + async _initialize(progress2) { + for (const page of this._context.pages()) + this._onPage(page); + this._eventListeners = [ + eventsHelper.addEventListener(this._context, BrowserContext.Events.Page, this._onPage.bind(this)), + eventsHelper.addEventListener(this._context, BrowserContext.Events.FrameAttached, (frame) => this._annotateFrameHierarchy(frame)) + ]; + const { javaScriptEnabled } = this._context._options; + const initScriptSource = `(${frameSnapshotStreamer})("${this._snapshotStreamer}", ${javaScriptEnabled || javaScriptEnabled === void 0})`; + this._initScript = await this._context.addInitScript(progress2, initScriptSource); + await progress2.race(this._context.safeNonStallingEvaluateInAllFrames(initScriptSource, "main")); + } + dispose() { + eventsHelper.removeEventListeners(this._eventListeners); + } + async _captureFrameSnapshot(frame, resetTargets) { + const needsHistoryReset = !!frame[kNeedsResetSymbol]; + frame[kNeedsResetSymbol] = false; + const reset = needsHistoryReset ? "history" : resetTargets ? "targets" : void 0; + const expression2 = `window["${this._snapshotStreamer}"].captureSnapshot(${JSON.stringify(reset)})`; + try { + return await frame.nonStallingRawEvaluateInExistingMainContext(expression2); + } catch (e) { + frame[kNeedsResetSymbol] = true; + debugLogger.log("error", e); + } + } + async captureSnapshot(page, callId, snapshotName, resetTargets) { + const snapshots = page.frames().map(async (frame) => { + const data = await this._captureFrameSnapshot(frame, resetTargets); + if (!data || !this._started) + return; + const snapshot3 = { + callId, + snapshotName, + pageId: page.guid, + frameId: frame.guid, + frameUrl: data.url, + doctype: data.doctype, + html: data.html, + viewport: data.viewport, + timestamp: monotonicTime(), + wallTime: data.wallTime, + collectionTime: data.collectionTime, + resourceOverrides: [], + isMainFrame: page.mainFrame() === frame + }; + for (const { url: url2, content, contentType } of data.resourceOverrides) { + if (typeof content === "string") { + const buffer = Buffer.from(content); + const sha1 = calculateSha1(buffer) + "." + (mime3.getExtension(contentType) || "dat"); + this._delegate.onSnapshotterBlob({ sha1, buffer }); + snapshot3.resourceOverrides.push({ url: url2, sha1 }); + } else { + snapshot3.resourceOverrides.push({ url: url2, ref: content }); + } + } + this._delegate.onFrameSnapshot(snapshot3); + }); + await Promise.all(snapshots); + } + _onPage(page) { + for (const frame of page.frames()) + this._annotateFrameHierarchy(frame); + } + _annotateFrameHierarchy(frame) { + (async () => { + const frameElement = await frame.frameElement(nullProgress); + const parent = frame.parentFrame(); + if (!parent) + return; + const context2 = await parent.mainContext(); + await context2?.evaluate(({ snapshotStreamer, frameElement: frameElement2, frameId }) => { + window[snapshotStreamer].markIframe(frameElement2, frameId); + }, { snapshotStreamer: this._snapshotStreamer, frameElement, frameId: frame.guid }); + frameElement.dispose(); + })().catch(() => { + }); + } + }; + kNeedsResetSymbol = Symbol("kNeedsReset"); + } +}); + +// packages/playwright-core/src/server/artifact.ts +var import_fs12, Artifact; +var init_artifact = __esm({ + "packages/playwright-core/src/server/artifact.ts"() { + "use strict"; + import_fs12 = __toESM(require("fs")); + init_manualPromise(); + init_assert(); + init_errors(); + init_instrumentation(); + Artifact = class extends SdkObject { + constructor(parent, localPath, unaccessibleErrorMessage, cancelCallback) { + super(parent, "artifact"); + this._finishedPromise = new ManualPromise(); + this._saveCallbacks = []; + this._finished = false; + this._deleted = false; + this._localPath = localPath; + this._unaccessibleErrorMessage = unaccessibleErrorMessage; + this._cancelCallback = cancelCallback; + } + async localPathAfterFinished(progress2) { + return await progress2.race(this._localPathAfterFinished()); + } + async failureError(progress2) { + return await progress2.race(this._failureError()); + } + async cancel(progress2) { + return await progress2.race(this._cancel()); + } + async delete(progress2) { + return await progress2.race(this._delete()); + } + localPath() { + return this._localPath; + } + async _localPathAfterFinished() { + if (this._unaccessibleErrorMessage) + throw new Error(this._unaccessibleErrorMessage); + await this._finishedPromise; + if (this._failureErrorValue) + throw this._failureErrorValue; + return this._localPath; + } + saveAs(progress2, saveCallback) { + if (this._unaccessibleErrorMessage) + throw new Error(this._unaccessibleErrorMessage); + if (this._deleted) + throw new Error(`File already deleted. Save before deleting.`); + if (this._failureErrorValue) + throw this._failureErrorValue; + if (this._finished) { + saveCallback(this._localPath).catch(() => { + }); + return; + } + this._saveCallbacks.push(saveCallback); + } + async _failureError() { + if (this._unaccessibleErrorMessage) + return this._unaccessibleErrorMessage; + await this._finishedPromise; + return this._failureErrorValue?.message || null; + } + async _cancel() { + assert(this._cancelCallback !== void 0); + return this._cancelCallback(); + } + async _delete() { + if (this._unaccessibleErrorMessage) + return; + const fileName = await this._localPathAfterFinished(); + if (this._deleted) + return; + this._deleted = true; + if (fileName) + await import_fs12.default.promises.unlink(fileName).catch((e) => { + }); + } + async deleteOnContextClose() { + if (this._deleted) + return; + this._deleted = true; + if (!this._unaccessibleErrorMessage) + await import_fs12.default.promises.unlink(this._localPath).catch((e) => { + }); + await this.reportFinished(new TargetClosedError(this.closeReason())); + } + async reportFinished(error) { + if (this._finished) + return; + this._finished = true; + this._failureErrorValue = error; + if (error) { + for (const callback of this._saveCallbacks) + await callback("", error); + } else { + for (const callback of this._saveCallbacks) + await callback(this._localPath); + } + this._saveCallbacks = []; + this._finishedPromise.resolve(); + } + }; + } +}); + +// packages/playwright-core/src/protocol/validatorPrimitives.ts +function findValidator(type3, method, kind) { + const validator = maybeFindValidator(type3, method, kind); + if (!validator) + throw new ValidationError(`Unknown scheme for ${kind}: ${type3}.${method}`); + return validator; +} +function maybeFindValidator(type3, method, kind) { + const schemeName = type3 + (kind === "Initializer" ? "" : method[0].toUpperCase() + method.substring(1)) + kind; + return scheme[schemeName]; +} +function createMetadataValidator() { + return tOptional(scheme["Metadata"]); +} +function createWaitInfoValidator() { + return scheme["WaitInfo"]; +} +var ValidationError, scheme, tFloat, tInt, tBoolean, tString, tBinary, tAny, tOptional, tArray, tObject, tEnum, tChannel, tType; +var init_validatorPrimitives = __esm({ + "packages/playwright-core/src/protocol/validatorPrimitives.ts"() { + "use strict"; + ValidationError = class extends Error { + }; + scheme = {}; + tFloat = (arg, path59, context2) => { + if (arg instanceof Number) + return arg.valueOf(); + if (typeof arg === "number") + return arg; + throw new ValidationError(`${path59}: expected float, got ${typeof arg}`); + }; + tInt = (arg, path59, context2) => { + let value2; + if (arg instanceof Number) + value2 = arg.valueOf(); + else if (typeof arg === "number") + value2 = arg; + else + throw new ValidationError(`${path59}: expected integer, got ${typeof arg}`); + if (!Number.isInteger(value2)) + throw new ValidationError(`${path59}: expected integer, got float ${value2}`); + return value2; + }; + tBoolean = (arg, path59, context2) => { + if (arg instanceof Boolean) + return arg.valueOf(); + if (typeof arg === "boolean") + return arg; + throw new ValidationError(`${path59}: expected boolean, got ${typeof arg}`); + }; + tString = (arg, path59, context2) => { + if (arg instanceof String) + return arg.valueOf(); + if (typeof arg === "string") + return arg; + throw new ValidationError(`${path59}: expected string, got ${typeof arg}`); + }; + tBinary = (arg, path59, context2) => { + if (context2.binary === "fromBase64") { + if (arg instanceof String) + return Buffer.from(arg.valueOf(), "base64"); + if (typeof arg === "string") + return Buffer.from(arg, "base64"); + throw new ValidationError(`${path59}: expected base64-encoded buffer, got ${typeof arg}`); + } + if (context2.binary === "toBase64") { + if (!(arg instanceof Buffer)) + throw new ValidationError(`${path59}: expected Buffer, got ${typeof arg}`); + return arg.toString("base64"); + } + if (context2.binary === "buffer") { + if (!(arg instanceof Buffer) && !(arg instanceof Object)) + throw new ValidationError(`${path59}: expected Buffer, got ${typeof arg}`); + return arg; + } + throw new ValidationError(`Unsupported binary behavior "${context2.binary}"`); + }; + tAny = (arg, path59, context2) => { + return arg; + }; + tOptional = (v) => { + return (arg, path59, context2) => { + if (Object.is(arg, void 0)) + return arg; + return v(arg, path59, context2); + }; + }; + tArray = (v) => { + return (arg, path59, context2) => { + if (!Array.isArray(arg)) + throw new ValidationError(`${path59}: expected array, got ${typeof arg}`); + return arg.map((x, index) => v(x, path59 + "[" + index + "]", context2)); + }; + }; + tObject = (s) => { + return (arg, path59, context2) => { + if (Object.is(arg, null)) + throw new ValidationError(`${path59}: expected object, got null`); + if (typeof arg !== "object") + throw new ValidationError(`${path59}: expected object, got ${typeof arg}`); + const result2 = {}; + for (const [key, v] of Object.entries(s)) { + const value2 = v(arg[key], path59 ? path59 + "." + key : key, context2); + if (!Object.is(value2, void 0)) + result2[key] = value2; + } + if (context2.isUnderTest()) { + for (const [key, value2] of Object.entries(arg)) { + if (key.startsWith("__testHook")) + result2[key] = value2; + } + } + return result2; + }; + }; + tEnum = (e) => { + return (arg, path59, context2) => { + if (!e.includes(arg)) + throw new ValidationError(`${path59}: expected one of (${e.join("|")})`); + return arg; + }; + }; + tChannel = (names) => { + return (arg, path59, context2) => { + return context2.tChannelImpl(names, arg, path59, context2); + }; + }; + tType = (name) => { + return (arg, path59, context2) => { + const v = scheme[name]; + if (!v) + throw new ValidationError(path59 + ': unknown type "' + name + '"'); + return v(arg, path59, context2); + }; + }; + } +}); + +// packages/playwright-core/src/protocol/validator.ts +var init_validator = __esm({ + "packages/playwright-core/src/protocol/validator.ts"() { + "use strict"; + init_validatorPrimitives(); + init_validatorPrimitives(); + scheme.AndroidInitializer = tOptional(tObject({})); + scheme.AndroidDevicesParams = tObject({ + host: tOptional(tString), + port: tOptional(tInt), + omitDriverInstall: tOptional(tBoolean) + }); + scheme.AndroidDevicesResult = tObject({ + devices: tArray(tChannel(["AndroidDevice"])) + }); + scheme.AndroidSocketInitializer = tOptional(tObject({})); + scheme.AndroidSocketDataEvent = tObject({ + data: tBinary + }); + scheme.AndroidSocketCloseEvent = tOptional(tObject({})); + scheme.AndroidSocketWriteParams = tObject({ + data: tBinary + }); + scheme.AndroidSocketWriteResult = tOptional(tObject({})); + scheme.AndroidSocketCloseParams = tOptional(tObject({})); + scheme.AndroidSocketCloseResult = tOptional(tObject({})); + scheme.AndroidDeviceInitializer = tObject({ + model: tString, + serial: tString + }); + scheme.AndroidDeviceCloseEvent = tOptional(tObject({})); + scheme.AndroidDeviceWebViewAddedEvent = tObject({ + webView: tType("AndroidWebView") + }); + scheme.AndroidDeviceWebViewRemovedEvent = tObject({ + socketName: tString + }); + scheme.AndroidDeviceWaitParams = tObject({ + androidSelector: tType("AndroidSelector"), + state: tOptional(tEnum(["gone"])), + timeout: tFloat + }); + scheme.AndroidDeviceWaitResult = tOptional(tObject({})); + scheme.AndroidDeviceFillParams = tObject({ + androidSelector: tType("AndroidSelector"), + text: tString, + timeout: tFloat + }); + scheme.AndroidDeviceFillResult = tOptional(tObject({})); + scheme.AndroidDeviceTapParams = tObject({ + androidSelector: tType("AndroidSelector"), + duration: tOptional(tFloat), + timeout: tFloat + }); + scheme.AndroidDeviceTapResult = tOptional(tObject({})); + scheme.AndroidDeviceDragParams = tObject({ + androidSelector: tType("AndroidSelector"), + dest: tType("Point"), + speed: tOptional(tFloat), + timeout: tFloat + }); + scheme.AndroidDeviceDragResult = tOptional(tObject({})); + scheme.AndroidDeviceFlingParams = tObject({ + androidSelector: tType("AndroidSelector"), + direction: tEnum(["up", "down", "left", "right"]), + speed: tOptional(tFloat), + timeout: tFloat + }); + scheme.AndroidDeviceFlingResult = tOptional(tObject({})); + scheme.AndroidDeviceLongTapParams = tObject({ + androidSelector: tType("AndroidSelector"), + timeout: tFloat + }); + scheme.AndroidDeviceLongTapResult = tOptional(tObject({})); + scheme.AndroidDevicePinchCloseParams = tObject({ + androidSelector: tType("AndroidSelector"), + percent: tFloat, + speed: tOptional(tFloat), + timeout: tFloat + }); + scheme.AndroidDevicePinchCloseResult = tOptional(tObject({})); + scheme.AndroidDevicePinchOpenParams = tObject({ + androidSelector: tType("AndroidSelector"), + percent: tFloat, + speed: tOptional(tFloat), + timeout: tFloat + }); + scheme.AndroidDevicePinchOpenResult = tOptional(tObject({})); + scheme.AndroidDeviceScrollParams = tObject({ + androidSelector: tType("AndroidSelector"), + direction: tEnum(["up", "down", "left", "right"]), + percent: tFloat, + speed: tOptional(tFloat), + timeout: tFloat + }); + scheme.AndroidDeviceScrollResult = tOptional(tObject({})); + scheme.AndroidDeviceSwipeParams = tObject({ + androidSelector: tType("AndroidSelector"), + direction: tEnum(["up", "down", "left", "right"]), + percent: tFloat, + speed: tOptional(tFloat), + timeout: tFloat + }); + scheme.AndroidDeviceSwipeResult = tOptional(tObject({})); + scheme.AndroidDeviceInfoParams = tObject({ + androidSelector: tType("AndroidSelector") + }); + scheme.AndroidDeviceInfoResult = tObject({ + info: tType("AndroidElementInfo") + }); + scheme.AndroidDeviceScreenshotParams = tOptional(tObject({})); + scheme.AndroidDeviceScreenshotResult = tObject({ + binary: tBinary + }); + scheme.AndroidDeviceInputTypeParams = tObject({ + text: tString + }); + scheme.AndroidDeviceInputTypeResult = tOptional(tObject({})); + scheme.AndroidDeviceInputPressParams = tObject({ + key: tString + }); + scheme.AndroidDeviceInputPressResult = tOptional(tObject({})); + scheme.AndroidDeviceInputTapParams = tObject({ + point: tType("Point") + }); + scheme.AndroidDeviceInputTapResult = tOptional(tObject({})); + scheme.AndroidDeviceInputSwipeParams = tObject({ + segments: tArray(tType("Point")), + steps: tInt + }); + scheme.AndroidDeviceInputSwipeResult = tOptional(tObject({})); + scheme.AndroidDeviceInputDragParams = tObject({ + from: tType("Point"), + to: tType("Point"), + steps: tInt + }); + scheme.AndroidDeviceInputDragResult = tOptional(tObject({})); + scheme.AndroidDeviceLaunchBrowserParams = tObject({ + noDefaultViewport: tOptional(tBoolean), + viewport: tOptional(tObject({ + width: tInt, + height: tInt + })), + screen: tOptional(tObject({ + width: tInt, + height: tInt + })), + ignoreHTTPSErrors: tOptional(tBoolean), + clientCertificates: tOptional(tArray(tObject({ + origin: tString, + cert: tOptional(tBinary), + key: tOptional(tBinary), + passphrase: tOptional(tString), + pfx: tOptional(tBinary) + }))), + javaScriptEnabled: tOptional(tBoolean), + bypassCSP: tOptional(tBoolean), + userAgent: tOptional(tString), + locale: tOptional(tString), + timezoneId: tOptional(tString), + geolocation: tOptional(tObject({ + longitude: tFloat, + latitude: tFloat, + accuracy: tOptional(tFloat) + })), + permissions: tOptional(tArray(tString)), + extraHTTPHeaders: tOptional(tArray(tType("NameValue"))), + offline: tOptional(tBoolean), + httpCredentials: tOptional(tObject({ + username: tString, + password: tString, + origin: tOptional(tString), + send: tOptional(tEnum(["always", "unauthorized"])) + })), + deviceScaleFactor: tOptional(tFloat), + isMobile: tOptional(tBoolean), + hasTouch: tOptional(tBoolean), + colorScheme: tOptional(tEnum(["dark", "light", "no-preference", "no-override"])), + reducedMotion: tOptional(tEnum(["reduce", "no-preference", "no-override"])), + forcedColors: tOptional(tEnum(["active", "none", "no-override"])), + acceptDownloads: tOptional(tEnum(["accept", "deny", "internal-browser-default"])), + contrast: tOptional(tEnum(["no-preference", "more", "no-override"])), + baseURL: tOptional(tString), + recordVideo: tOptional(tObject({ + dir: tOptional(tString), + size: tOptional(tObject({ + width: tInt, + height: tInt + })), + showActions: tOptional(tObject({ + duration: tOptional(tFloat), + position: tOptional(tEnum(["top-left", "top", "top-right", "bottom-left", "bottom", "bottom-right"])), + fontSize: tOptional(tInt), + cursor: tOptional(tEnum(["none", "pointer"])) + })) + })), + strictSelectors: tOptional(tBoolean), + serviceWorkers: tOptional(tEnum(["allow", "block"])), + selectorEngines: tOptional(tArray(tType("SelectorEngine"))), + testIdAttributeName: tOptional(tString), + pkg: tOptional(tString), + args: tOptional(tArray(tString)), + proxy: tOptional(tObject({ + server: tString, + bypass: tOptional(tString), + username: tOptional(tString), + password: tOptional(tString) + })) + }); + scheme.AndroidDeviceLaunchBrowserResult = tObject({ + context: tChannel(["BrowserContext"]) + }); + scheme.AndroidDeviceOpenParams = tObject({ + command: tString + }); + scheme.AndroidDeviceOpenResult = tObject({ + socket: tChannel(["AndroidSocket"]) + }); + scheme.AndroidDeviceShellParams = tObject({ + command: tString + }); + scheme.AndroidDeviceShellResult = tObject({ + result: tBinary + }); + scheme.AndroidDeviceInstallApkParams = tObject({ + file: tBinary, + args: tOptional(tArray(tString)) + }); + scheme.AndroidDeviceInstallApkResult = tOptional(tObject({})); + scheme.AndroidDevicePushParams = tObject({ + file: tBinary, + path: tString, + mode: tOptional(tInt) + }); + scheme.AndroidDevicePushResult = tOptional(tObject({})); + scheme.AndroidDeviceConnectToWebViewParams = tObject({ + socketName: tString + }); + scheme.AndroidDeviceConnectToWebViewResult = tObject({ + context: tChannel(["BrowserContext"]) + }); + scheme.AndroidDeviceCloseParams = tOptional(tObject({})); + scheme.AndroidDeviceCloseResult = tOptional(tObject({})); + scheme.AndroidWebView = tObject({ + pid: tInt, + pkg: tString, + socketName: tString + }); + scheme.AndroidSelector = tObject({ + checkable: tOptional(tBoolean), + checked: tOptional(tBoolean), + clazz: tOptional(tString), + clickable: tOptional(tBoolean), + depth: tOptional(tInt), + desc: tOptional(tString), + enabled: tOptional(tBoolean), + focusable: tOptional(tBoolean), + focused: tOptional(tBoolean), + hasChild: tOptional(tObject({ + androidSelector: tType("AndroidSelector") + })), + hasDescendant: tOptional(tObject({ + androidSelector: tType("AndroidSelector"), + maxDepth: tOptional(tInt) + })), + longClickable: tOptional(tBoolean), + pkg: tOptional(tString), + res: tOptional(tString), + scrollable: tOptional(tBoolean), + selected: tOptional(tBoolean), + text: tOptional(tString) + }); + scheme.AndroidElementInfo = tObject({ + children: tOptional(tArray(tType("AndroidElementInfo"))), + clazz: tString, + desc: tString, + res: tString, + pkg: tString, + text: tString, + bounds: tType("Rect"), + checkable: tBoolean, + checked: tBoolean, + clickable: tBoolean, + enabled: tBoolean, + focusable: tBoolean, + focused: tBoolean, + longClickable: tBoolean, + scrollable: tBoolean, + selected: tBoolean + }); + scheme.APIRequestContextInitializer = tObject({ + tracing: tChannel(["Tracing"]) + }); + scheme.APIRequestContextFetchParams = tObject({ + url: tString, + encodedParams: tOptional(tString), + params: tOptional(tArray(tType("NameValue"))), + method: tOptional(tString), + headers: tOptional(tArray(tType("NameValue"))), + postData: tOptional(tBinary), + jsonData: tOptional(tString), + formData: tOptional(tArray(tType("NameValue"))), + multipartData: tOptional(tArray(tType("FormField"))), + timeout: tFloat, + failOnStatusCode: tOptional(tBoolean), + ignoreHTTPSErrors: tOptional(tBoolean), + maxRedirects: tOptional(tInt), + maxRetries: tOptional(tInt) + }); + scheme.APIRequestContextFetchResult = tObject({ + response: tType("APIResponse") + }); + scheme.APIRequestContextFetchResponseBodyParams = tObject({ + fetchUid: tString + }); + scheme.APIRequestContextFetchResponseBodyResult = tObject({ + binary: tOptional(tBinary) + }); + scheme.APIRequestContextFetchLogParams = tObject({ + fetchUid: tString + }); + scheme.APIRequestContextFetchLogResult = tObject({ + log: tArray(tString) + }); + scheme.APIRequestContextStorageStateParams = tObject({ + indexedDB: tOptional(tBoolean) + }); + scheme.APIRequestContextStorageStateResult = tObject({ + cookies: tArray(tType("NetworkCookie")), + origins: tArray(tType("OriginStorage")) + }); + scheme.APIRequestContextDisposeAPIResponseParams = tObject({ + fetchUid: tString + }); + scheme.APIRequestContextDisposeAPIResponseResult = tOptional(tObject({})); + scheme.APIRequestContextDisposeParams = tObject({ + reason: tOptional(tString) + }); + scheme.APIRequestContextDisposeResult = tOptional(tObject({})); + scheme.APIResponse = tObject({ + fetchUid: tString, + url: tString, + status: tInt, + statusText: tString, + headers: tArray(tType("NameValue")), + securityDetails: tOptional(tType("SecurityDetails")), + serverAddr: tOptional(tType("RemoteAddr")) + }); + scheme.ArtifactInitializer = tObject({ + absolutePath: tString + }); + scheme.ArtifactPathAfterFinishedParams = tOptional(tObject({})); + scheme.ArtifactPathAfterFinishedResult = tObject({ + value: tString + }); + scheme.ArtifactSaveAsParams = tObject({ + path: tString + }); + scheme.ArtifactSaveAsResult = tOptional(tObject({})); + scheme.ArtifactSaveAsStreamParams = tOptional(tObject({})); + scheme.ArtifactSaveAsStreamResult = tObject({ + stream: tChannel(["Stream"]) + }); + scheme.ArtifactFailureParams = tOptional(tObject({})); + scheme.ArtifactFailureResult = tObject({ + error: tOptional(tString) + }); + scheme.ArtifactStreamParams = tOptional(tObject({})); + scheme.ArtifactStreamResult = tObject({ + stream: tChannel(["Stream"]) + }); + scheme.ArtifactCancelParams = tOptional(tObject({})); + scheme.ArtifactCancelResult = tOptional(tObject({})); + scheme.ArtifactDeleteParams = tOptional(tObject({})); + scheme.ArtifactDeleteResult = tOptional(tObject({})); + scheme.StreamInitializer = tOptional(tObject({})); + scheme.StreamReadParams = tObject({ + size: tOptional(tInt) + }); + scheme.StreamReadResult = tObject({ + binary: tBinary + }); + scheme.StreamCloseParams = tOptional(tObject({})); + scheme.StreamCloseResult = tOptional(tObject({})); + scheme.WritableStreamInitializer = tOptional(tObject({})); + scheme.WritableStreamWriteParams = tObject({ + binary: tBinary + }); + scheme.WritableStreamWriteResult = tOptional(tObject({})); + scheme.WritableStreamCloseParams = tOptional(tObject({})); + scheme.WritableStreamCloseResult = tOptional(tObject({})); + scheme.BrowserInitializer = tObject({ + version: tString, + name: tString, + browserName: tEnum(["chromium", "firefox", "webkit"]) + }); + scheme.BrowserContextEvent = tObject({ + context: tChannel(["BrowserContext"]) + }); + scheme.BrowserCloseEvent = tOptional(tObject({})); + scheme.BrowserStartServerParams = tObject({ + title: tString, + workspaceDir: tOptional(tString), + metadata: tOptional(tAny), + host: tOptional(tString), + port: tOptional(tInt) + }); + scheme.BrowserStartServerResult = tObject({ + endpoint: tString + }); + scheme.BrowserStopServerParams = tOptional(tObject({})); + scheme.BrowserStopServerResult = tOptional(tObject({})); + scheme.BrowserCloseParams = tObject({ + reason: tOptional(tString) + }); + scheme.BrowserCloseResult = tOptional(tObject({})); + scheme.BrowserKillForTestsParams = tOptional(tObject({})); + scheme.BrowserKillForTestsResult = tOptional(tObject({})); + scheme.BrowserDefaultUserAgentForTestParams = tOptional(tObject({})); + scheme.BrowserDefaultUserAgentForTestResult = tObject({ + userAgent: tString + }); + scheme.BrowserNewContextParams = tObject({ + noDefaultViewport: tOptional(tBoolean), + viewport: tOptional(tObject({ + width: tInt, + height: tInt + })), + screen: tOptional(tObject({ + width: tInt, + height: tInt + })), + ignoreHTTPSErrors: tOptional(tBoolean), + clientCertificates: tOptional(tArray(tObject({ + origin: tString, + cert: tOptional(tBinary), + key: tOptional(tBinary), + passphrase: tOptional(tString), + pfx: tOptional(tBinary) + }))), + javaScriptEnabled: tOptional(tBoolean), + bypassCSP: tOptional(tBoolean), + userAgent: tOptional(tString), + locale: tOptional(tString), + timezoneId: tOptional(tString), + geolocation: tOptional(tObject({ + longitude: tFloat, + latitude: tFloat, + accuracy: tOptional(tFloat) + })), + permissions: tOptional(tArray(tString)), + extraHTTPHeaders: tOptional(tArray(tType("NameValue"))), + offline: tOptional(tBoolean), + httpCredentials: tOptional(tObject({ + username: tString, + password: tString, + origin: tOptional(tString), + send: tOptional(tEnum(["always", "unauthorized"])) + })), + deviceScaleFactor: tOptional(tFloat), + isMobile: tOptional(tBoolean), + hasTouch: tOptional(tBoolean), + colorScheme: tOptional(tEnum(["dark", "light", "no-preference", "no-override"])), + reducedMotion: tOptional(tEnum(["reduce", "no-preference", "no-override"])), + forcedColors: tOptional(tEnum(["active", "none", "no-override"])), + acceptDownloads: tOptional(tEnum(["accept", "deny", "internal-browser-default"])), + contrast: tOptional(tEnum(["no-preference", "more", "no-override"])), + baseURL: tOptional(tString), + recordVideo: tOptional(tObject({ + dir: tOptional(tString), + size: tOptional(tObject({ + width: tInt, + height: tInt + })), + showActions: tOptional(tObject({ + duration: tOptional(tFloat), + position: tOptional(tEnum(["top-left", "top", "top-right", "bottom-left", "bottom", "bottom-right"])), + fontSize: tOptional(tInt), + cursor: tOptional(tEnum(["none", "pointer"])) + })) + })), + strictSelectors: tOptional(tBoolean), + serviceWorkers: tOptional(tEnum(["allow", "block"])), + selectorEngines: tOptional(tArray(tType("SelectorEngine"))), + testIdAttributeName: tOptional(tString), + proxy: tOptional(tObject({ + server: tString, + bypass: tOptional(tString), + username: tOptional(tString), + password: tOptional(tString) + })), + storageState: tOptional(tObject({ + cookies: tOptional(tArray(tType("SetNetworkCookie"))), + origins: tOptional(tArray(tType("SetOriginStorage"))) + })) + }); + scheme.BrowserNewContextResult = tObject({ + context: tChannel(["BrowserContext"]) + }); + scheme.BrowserNewContextForReuseParams = tObject({ + noDefaultViewport: tOptional(tBoolean), + viewport: tOptional(tObject({ + width: tInt, + height: tInt + })), + screen: tOptional(tObject({ + width: tInt, + height: tInt + })), + ignoreHTTPSErrors: tOptional(tBoolean), + clientCertificates: tOptional(tArray(tObject({ + origin: tString, + cert: tOptional(tBinary), + key: tOptional(tBinary), + passphrase: tOptional(tString), + pfx: tOptional(tBinary) + }))), + javaScriptEnabled: tOptional(tBoolean), + bypassCSP: tOptional(tBoolean), + userAgent: tOptional(tString), + locale: tOptional(tString), + timezoneId: tOptional(tString), + geolocation: tOptional(tObject({ + longitude: tFloat, + latitude: tFloat, + accuracy: tOptional(tFloat) + })), + permissions: tOptional(tArray(tString)), + extraHTTPHeaders: tOptional(tArray(tType("NameValue"))), + offline: tOptional(tBoolean), + httpCredentials: tOptional(tObject({ + username: tString, + password: tString, + origin: tOptional(tString), + send: tOptional(tEnum(["always", "unauthorized"])) + })), + deviceScaleFactor: tOptional(tFloat), + isMobile: tOptional(tBoolean), + hasTouch: tOptional(tBoolean), + colorScheme: tOptional(tEnum(["dark", "light", "no-preference", "no-override"])), + reducedMotion: tOptional(tEnum(["reduce", "no-preference", "no-override"])), + forcedColors: tOptional(tEnum(["active", "none", "no-override"])), + acceptDownloads: tOptional(tEnum(["accept", "deny", "internal-browser-default"])), + contrast: tOptional(tEnum(["no-preference", "more", "no-override"])), + baseURL: tOptional(tString), + recordVideo: tOptional(tObject({ + dir: tOptional(tString), + size: tOptional(tObject({ + width: tInt, + height: tInt + })), + showActions: tOptional(tObject({ + duration: tOptional(tFloat), + position: tOptional(tEnum(["top-left", "top", "top-right", "bottom-left", "bottom", "bottom-right"])), + fontSize: tOptional(tInt), + cursor: tOptional(tEnum(["none", "pointer"])) + })) + })), + strictSelectors: tOptional(tBoolean), + serviceWorkers: tOptional(tEnum(["allow", "block"])), + selectorEngines: tOptional(tArray(tType("SelectorEngine"))), + testIdAttributeName: tOptional(tString), + proxy: tOptional(tObject({ + server: tString, + bypass: tOptional(tString), + username: tOptional(tString), + password: tOptional(tString) + })), + storageState: tOptional(tObject({ + cookies: tOptional(tArray(tType("SetNetworkCookie"))), + origins: tOptional(tArray(tType("SetOriginStorage"))) + })) + }); + scheme.BrowserNewContextForReuseResult = tObject({ + context: tChannel(["BrowserContext"]) + }); + scheme.BrowserDisconnectFromReusedContextParams = tObject({ + reason: tString + }); + scheme.BrowserDisconnectFromReusedContextResult = tOptional(tObject({})); + scheme.BrowserNewBrowserCDPSessionParams = tOptional(tObject({})); + scheme.BrowserNewBrowserCDPSessionResult = tObject({ + session: tChannel(["CDPSession"]) + }); + scheme.BrowserStartTracingParams = tObject({ + page: tOptional(tChannel(["Page"])), + screenshots: tOptional(tBoolean), + categories: tOptional(tArray(tString)) + }); + scheme.BrowserStartTracingResult = tOptional(tObject({})); + scheme.BrowserStopTracingParams = tOptional(tObject({})); + scheme.BrowserStopTracingResult = tObject({ + artifact: tChannel(["Artifact"]) + }); + scheme.BrowserContextInitializer = tObject({ + debugger: tChannel(["Debugger"]), + requestContext: tChannel(["APIRequestContext"]), + tracing: tChannel(["Tracing"]), + options: tObject({ + noDefaultViewport: tOptional(tBoolean), + viewport: tOptional(tObject({ + width: tInt, + height: tInt + })), + screen: tOptional(tObject({ + width: tInt, + height: tInt + })), + ignoreHTTPSErrors: tOptional(tBoolean), + clientCertificates: tOptional(tArray(tObject({ + origin: tString, + cert: tOptional(tBinary), + key: tOptional(tBinary), + passphrase: tOptional(tString), + pfx: tOptional(tBinary) + }))), + javaScriptEnabled: tOptional(tBoolean), + bypassCSP: tOptional(tBoolean), + userAgent: tOptional(tString), + locale: tOptional(tString), + timezoneId: tOptional(tString), + geolocation: tOptional(tObject({ + longitude: tFloat, + latitude: tFloat, + accuracy: tOptional(tFloat) + })), + permissions: tOptional(tArray(tString)), + extraHTTPHeaders: tOptional(tArray(tType("NameValue"))), + offline: tOptional(tBoolean), + httpCredentials: tOptional(tObject({ + username: tString, + password: tString, + origin: tOptional(tString), + send: tOptional(tEnum(["always", "unauthorized"])) + })), + deviceScaleFactor: tOptional(tFloat), + isMobile: tOptional(tBoolean), + hasTouch: tOptional(tBoolean), + colorScheme: tOptional(tEnum(["dark", "light", "no-preference", "no-override"])), + reducedMotion: tOptional(tEnum(["reduce", "no-preference", "no-override"])), + forcedColors: tOptional(tEnum(["active", "none", "no-override"])), + acceptDownloads: tOptional(tEnum(["accept", "deny", "internal-browser-default"])), + contrast: tOptional(tEnum(["no-preference", "more", "no-override"])), + baseURL: tOptional(tString), + recordVideo: tOptional(tObject({ + dir: tOptional(tString), + size: tOptional(tObject({ + width: tInt, + height: tInt + })), + showActions: tOptional(tObject({ + duration: tOptional(tFloat), + position: tOptional(tEnum(["top-left", "top", "top-right", "bottom-left", "bottom", "bottom-right"])), + fontSize: tOptional(tInt), + cursor: tOptional(tEnum(["none", "pointer"])) + })) + })), + strictSelectors: tOptional(tBoolean), + serviceWorkers: tOptional(tEnum(["allow", "block"])), + selectorEngines: tOptional(tArray(tType("SelectorEngine"))), + testIdAttributeName: tOptional(tString) + }) + }); + scheme.BrowserContextBindingCallEvent = tObject({ + binding: tChannel(["BindingCall"]) + }); + scheme.BrowserContextConsoleEvent = tObject({ + type: tString, + text: tString, + args: tArray(tChannel(["ElementHandle", "JSHandle"])), + location: tObject({ + url: tString, + lineNumber: tInt, + columnNumber: tInt + }), + timestamp: tFloat, + page: tOptional(tChannel(["Page"])), + worker: tOptional(tChannel(["Worker"])) + }); + scheme.BrowserContextCloseEvent = tOptional(tObject({})); + scheme.BrowserContextDialogEvent = tObject({ + dialog: tChannel(["Dialog"]) + }); + scheme.BrowserContextPageEvent = tObject({ + page: tChannel(["Page"]) + }); + scheme.BrowserContextPageErrorEvent = tObject({ + error: tType("SerializedError"), + page: tChannel(["Page"]), + location: tObject({ + url: tString, + line: tInt, + column: tInt + }) + }); + scheme.BrowserContextRouteEvent = tObject({ + route: tChannel(["Route"]) + }); + scheme.BrowserContextWebSocketRouteEvent = tObject({ + webSocketRoute: tChannel(["WebSocketRoute"]) + }); + scheme.BrowserContextServiceWorkerEvent = tObject({ + worker: tChannel(["Worker"]) + }); + scheme.BrowserContextRequestEvent = tObject({ + request: tChannel(["Request"]), + page: tOptional(tChannel(["Page"])) + }); + scheme.BrowserContextRequestFailedEvent = tObject({ + request: tChannel(["Request"]), + failureText: tOptional(tString), + responseEndTiming: tFloat, + page: tOptional(tChannel(["Page"])) + }); + scheme.BrowserContextRequestFinishedEvent = tObject({ + request: tChannel(["Request"]), + response: tOptional(tChannel(["Response"])), + responseEndTiming: tFloat, + page: tOptional(tChannel(["Page"])) + }); + scheme.BrowserContextResponseEvent = tObject({ + response: tChannel(["Response"]), + page: tOptional(tChannel(["Page"])) + }); + scheme.BrowserContextRecorderEventEvent = tObject({ + event: tEnum(["actionAdded", "actionUpdated", "signalAdded"]), + data: tAny, + page: tChannel(["Page"]), + code: tString + }); + scheme.BrowserContextAddCookiesParams = tObject({ + cookies: tArray(tType("SetNetworkCookie")) + }); + scheme.BrowserContextAddCookiesResult = tOptional(tObject({})); + scheme.BrowserContextAddInitScriptParams = tObject({ + source: tString + }); + scheme.BrowserContextAddInitScriptResult = tObject({ + disposable: tChannel(["Disposable"]) + }); + scheme.BrowserContextClearCookiesParams = tObject({ + name: tOptional(tString), + nameRegexSource: tOptional(tString), + nameRegexFlags: tOptional(tString), + domain: tOptional(tString), + domainRegexSource: tOptional(tString), + domainRegexFlags: tOptional(tString), + path: tOptional(tString), + pathRegexSource: tOptional(tString), + pathRegexFlags: tOptional(tString) + }); + scheme.BrowserContextClearCookiesResult = tOptional(tObject({})); + scheme.BrowserContextClearPermissionsParams = tOptional(tObject({})); + scheme.BrowserContextClearPermissionsResult = tOptional(tObject({})); + scheme.BrowserContextCloseParams = tObject({ + reason: tOptional(tString) + }); + scheme.BrowserContextCloseResult = tOptional(tObject({})); + scheme.BrowserContextCookiesParams = tObject({ + urls: tArray(tString) + }); + scheme.BrowserContextCookiesResult = tObject({ + cookies: tArray(tType("NetworkCookie")) + }); + scheme.BrowserContextExposeBindingParams = tObject({ + name: tString + }); + scheme.BrowserContextExposeBindingResult = tObject({ + disposable: tChannel(["Disposable"]) + }); + scheme.BrowserContextGrantPermissionsParams = tObject({ + permissions: tArray(tString), + origin: tOptional(tString) + }); + scheme.BrowserContextGrantPermissionsResult = tOptional(tObject({})); + scheme.BrowserContextNewPageParams = tOptional(tObject({})); + scheme.BrowserContextNewPageResult = tObject({ + page: tChannel(["Page"]) + }); + scheme.BrowserContextRegisterSelectorEngineParams = tObject({ + selectorEngine: tType("SelectorEngine") + }); + scheme.BrowserContextRegisterSelectorEngineResult = tOptional(tObject({})); + scheme.BrowserContextSetTestIdAttributeNameParams = tObject({ + testIdAttributeName: tString + }); + scheme.BrowserContextSetTestIdAttributeNameResult = tOptional(tObject({})); + scheme.BrowserContextSetExtraHTTPHeadersParams = tObject({ + headers: tArray(tType("NameValue")) + }); + scheme.BrowserContextSetExtraHTTPHeadersResult = tOptional(tObject({})); + scheme.BrowserContextSetGeolocationParams = tObject({ + geolocation: tOptional(tObject({ + longitude: tFloat, + latitude: tFloat, + accuracy: tOptional(tFloat) + })) + }); + scheme.BrowserContextSetGeolocationResult = tOptional(tObject({})); + scheme.BrowserContextSetHTTPCredentialsParams = tObject({ + httpCredentials: tOptional(tObject({ + username: tString, + password: tString, + origin: tOptional(tString) + })) + }); + scheme.BrowserContextSetHTTPCredentialsResult = tOptional(tObject({})); + scheme.BrowserContextSetNetworkInterceptionPatternsParams = tObject({ + patterns: tArray(tObject({ + glob: tOptional(tString), + regexSource: tOptional(tString), + regexFlags: tOptional(tString), + urlPattern: tOptional(tType("URLPattern")) + })) + }); + scheme.BrowserContextSetNetworkInterceptionPatternsResult = tOptional(tObject({})); + scheme.BrowserContextSetWebSocketInterceptionPatternsParams = tObject({ + patterns: tArray(tObject({ + glob: tOptional(tString), + regexSource: tOptional(tString), + regexFlags: tOptional(tString), + urlPattern: tOptional(tType("URLPattern")) + })) + }); + scheme.BrowserContextSetWebSocketInterceptionPatternsResult = tOptional(tObject({})); + scheme.BrowserContextSetOfflineParams = tObject({ + offline: tBoolean + }); + scheme.BrowserContextSetOfflineResult = tOptional(tObject({})); + scheme.BrowserContextStorageStateParams = tObject({ + indexedDB: tOptional(tBoolean) + }); + scheme.BrowserContextStorageStateResult = tObject({ + cookies: tArray(tType("NetworkCookie")), + origins: tArray(tType("OriginStorage")) + }); + scheme.BrowserContextSetStorageStateParams = tObject({ + storageState: tOptional(tObject({ + cookies: tOptional(tArray(tType("SetNetworkCookie"))), + origins: tOptional(tArray(tType("SetOriginStorage"))) + })) + }); + scheme.BrowserContextSetStorageStateResult = tOptional(tObject({})); + scheme.BrowserContextPauseParams = tOptional(tObject({})); + scheme.BrowserContextPauseResult = tOptional(tObject({})); + scheme.BrowserContextEnableRecorderParams = tObject({ + language: tOptional(tString), + mode: tOptional(tEnum(["inspecting", "recording"])), + recorderMode: tOptional(tEnum(["default", "api"])), + pauseOnNextStatement: tOptional(tBoolean), + testIdAttributeName: tOptional(tString), + launchOptions: tOptional(tAny), + contextOptions: tOptional(tAny), + device: tOptional(tString), + saveStorage: tOptional(tString), + outputFile: tOptional(tString), + handleSIGINT: tOptional(tBoolean), + omitCallTracking: tOptional(tBoolean) + }); + scheme.BrowserContextEnableRecorderResult = tOptional(tObject({})); + scheme.BrowserContextDisableRecorderParams = tOptional(tObject({})); + scheme.BrowserContextDisableRecorderResult = tOptional(tObject({})); + scheme.BrowserContextExposeConsoleApiParams = tOptional(tObject({})); + scheme.BrowserContextExposeConsoleApiResult = tOptional(tObject({})); + scheme.BrowserContextNewCDPSessionParams = tObject({ + page: tOptional(tChannel(["Page"])), + frame: tOptional(tChannel(["Frame"])) + }); + scheme.BrowserContextNewCDPSessionResult = tObject({ + session: tChannel(["CDPSession"]) + }); + scheme.BrowserContextCreateTempFilesParams = tObject({ + rootDirName: tOptional(tString), + items: tArray(tObject({ + name: tString, + lastModifiedMs: tOptional(tFloat) + })) + }); + scheme.BrowserContextCreateTempFilesResult = tObject({ + rootDir: tOptional(tChannel(["WritableStream"])), + writableStreams: tArray(tChannel(["WritableStream"])) + }); + scheme.BrowserContextUpdateSubscriptionParams = tObject({ + event: tEnum(["console", "dialog", "request", "response", "requestFinished", "requestFailed"]), + enabled: tBoolean + }); + scheme.BrowserContextUpdateSubscriptionResult = tOptional(tObject({})); + scheme.BrowserContextClockFastForwardParams = tObject({ + ticksNumber: tOptional(tFloat), + ticksString: tOptional(tString) + }); + scheme.BrowserContextClockFastForwardResult = tOptional(tObject({})); + scheme.BrowserContextClockInstallParams = tObject({ + timeNumber: tOptional(tFloat), + timeString: tOptional(tString) + }); + scheme.BrowserContextClockInstallResult = tOptional(tObject({})); + scheme.BrowserContextClockPauseAtParams = tObject({ + timeNumber: tOptional(tFloat), + timeString: tOptional(tString) + }); + scheme.BrowserContextClockPauseAtResult = tOptional(tObject({})); + scheme.BrowserContextClockResumeParams = tOptional(tObject({})); + scheme.BrowserContextClockResumeResult = tOptional(tObject({})); + scheme.BrowserContextClockRunForParams = tObject({ + ticksNumber: tOptional(tFloat), + ticksString: tOptional(tString) + }); + scheme.BrowserContextClockRunForResult = tOptional(tObject({})); + scheme.BrowserContextClockSetFixedTimeParams = tObject({ + timeNumber: tOptional(tFloat), + timeString: tOptional(tString) + }); + scheme.BrowserContextClockSetFixedTimeResult = tOptional(tObject({})); + scheme.BrowserContextClockSetSystemTimeParams = tObject({ + timeNumber: tOptional(tFloat), + timeString: tOptional(tString) + }); + scheme.BrowserContextClockSetSystemTimeResult = tOptional(tObject({})); + scheme.BrowserContextCredentialsInstallParams = tOptional(tObject({})); + scheme.BrowserContextCredentialsInstallResult = tOptional(tObject({})); + scheme.BrowserContextCredentialsCreateParams = tObject({ + rpId: tString, + id: tOptional(tString), + userHandle: tOptional(tString), + privateKey: tOptional(tString), + publicKey: tOptional(tString) + }); + scheme.BrowserContextCredentialsCreateResult = tObject({ + credential: tType("VirtualCredential") + }); + scheme.BrowserContextCredentialsGetParams = tObject({ + rpId: tOptional(tString), + id: tOptional(tString) + }); + scheme.BrowserContextCredentialsGetResult = tObject({ + credentials: tArray(tType("VirtualCredential")) + }); + scheme.BrowserContextCredentialsDeleteParams = tObject({ + id: tString + }); + scheme.BrowserContextCredentialsDeleteResult = tOptional(tObject({})); + scheme.BrowserTypeInitializer = tObject({ + executablePath: tString, + name: tString + }); + scheme.BrowserTypeLaunchParams = tObject({ + channel: tOptional(tString), + executablePath: tOptional(tString), + args: tOptional(tArray(tString)), + ignoreAllDefaultArgs: tOptional(tBoolean), + ignoreDefaultArgs: tOptional(tArray(tString)), + handleSIGINT: tOptional(tBoolean), + handleSIGTERM: tOptional(tBoolean), + handleSIGHUP: tOptional(tBoolean), + timeout: tFloat, + env: tOptional(tArray(tType("NameValue"))), + headless: tOptional(tBoolean), + proxy: tOptional(tObject({ + server: tString, + bypass: tOptional(tString), + username: tOptional(tString), + password: tOptional(tString) + })), + downloadsPath: tOptional(tString), + tracesDir: tOptional(tString), + artifactsDir: tOptional(tString), + chromiumSandbox: tOptional(tBoolean), + firefoxUserPrefs: tOptional(tAny), + cdpPort: tOptional(tInt), + slowMo: tOptional(tFloat) + }); + scheme.BrowserTypeLaunchResult = tObject({ + browser: tChannel(["Browser"]) + }); + scheme.BrowserTypeLaunchPersistentContextParams = tObject({ + channel: tOptional(tString), + executablePath: tOptional(tString), + args: tOptional(tArray(tString)), + ignoreAllDefaultArgs: tOptional(tBoolean), + ignoreDefaultArgs: tOptional(tArray(tString)), + handleSIGINT: tOptional(tBoolean), + handleSIGTERM: tOptional(tBoolean), + handleSIGHUP: tOptional(tBoolean), + timeout: tFloat, + env: tOptional(tArray(tType("NameValue"))), + headless: tOptional(tBoolean), + proxy: tOptional(tObject({ + server: tString, + bypass: tOptional(tString), + username: tOptional(tString), + password: tOptional(tString) + })), + downloadsPath: tOptional(tString), + tracesDir: tOptional(tString), + artifactsDir: tOptional(tString), + chromiumSandbox: tOptional(tBoolean), + firefoxUserPrefs: tOptional(tAny), + cdpPort: tOptional(tInt), + noDefaultViewport: tOptional(tBoolean), + viewport: tOptional(tObject({ + width: tInt, + height: tInt + })), + screen: tOptional(tObject({ + width: tInt, + height: tInt + })), + ignoreHTTPSErrors: tOptional(tBoolean), + clientCertificates: tOptional(tArray(tObject({ + origin: tString, + cert: tOptional(tBinary), + key: tOptional(tBinary), + passphrase: tOptional(tString), + pfx: tOptional(tBinary) + }))), + javaScriptEnabled: tOptional(tBoolean), + bypassCSP: tOptional(tBoolean), + userAgent: tOptional(tString), + locale: tOptional(tString), + timezoneId: tOptional(tString), + geolocation: tOptional(tObject({ + longitude: tFloat, + latitude: tFloat, + accuracy: tOptional(tFloat) + })), + permissions: tOptional(tArray(tString)), + extraHTTPHeaders: tOptional(tArray(tType("NameValue"))), + offline: tOptional(tBoolean), + httpCredentials: tOptional(tObject({ + username: tString, + password: tString, + origin: tOptional(tString), + send: tOptional(tEnum(["always", "unauthorized"])) + })), + deviceScaleFactor: tOptional(tFloat), + isMobile: tOptional(tBoolean), + hasTouch: tOptional(tBoolean), + colorScheme: tOptional(tEnum(["dark", "light", "no-preference", "no-override"])), + reducedMotion: tOptional(tEnum(["reduce", "no-preference", "no-override"])), + forcedColors: tOptional(tEnum(["active", "none", "no-override"])), + acceptDownloads: tOptional(tEnum(["accept", "deny", "internal-browser-default"])), + contrast: tOptional(tEnum(["no-preference", "more", "no-override"])), + baseURL: tOptional(tString), + recordVideo: tOptional(tObject({ + dir: tOptional(tString), + size: tOptional(tObject({ + width: tInt, + height: tInt + })), + showActions: tOptional(tObject({ + duration: tOptional(tFloat), + position: tOptional(tEnum(["top-left", "top", "top-right", "bottom-left", "bottom", "bottom-right"])), + fontSize: tOptional(tInt), + cursor: tOptional(tEnum(["none", "pointer"])) + })) + })), + strictSelectors: tOptional(tBoolean), + serviceWorkers: tOptional(tEnum(["allow", "block"])), + selectorEngines: tOptional(tArray(tType("SelectorEngine"))), + testIdAttributeName: tOptional(tString), + userDataDir: tString, + slowMo: tOptional(tFloat) + }); + scheme.BrowserTypeLaunchPersistentContextResult = tObject({ + browser: tChannel(["Browser"]), + context: tChannel(["BrowserContext"]) + }); + scheme.BrowserTypeConnectOverCDPParams = tObject({ + endpointURL: tOptional(tString), + headers: tOptional(tArray(tType("NameValue"))), + slowMo: tOptional(tFloat), + timeout: tFloat, + isLocal: tOptional(tBoolean), + noDefaults: tOptional(tBoolean), + artifactsDir: tOptional(tString), + transport: tOptional(tBinary) + }); + scheme.BrowserTypeConnectOverCDPResult = tObject({ + browser: tChannel(["Browser"]), + defaultContext: tOptional(tChannel(["BrowserContext"])) + }); + scheme.BrowserTypeConnectToWorkerParams = tObject({ + endpoint: tString, + timeout: tFloat + }); + scheme.BrowserTypeConnectToWorkerResult = tObject({ + worker: tChannel(["Worker"]) + }); + scheme.Metadata = tObject({ + location: tOptional(tObject({ + file: tString, + line: tOptional(tInt), + column: tOptional(tInt) + })), + title: tOptional(tString), + internal: tOptional(tBoolean), + stepId: tOptional(tString) + }); + scheme.ClientSideCallMetadata = tObject({ + id: tInt, + stack: tOptional(tArray(tType("StackFrame"))) + }); + scheme.SDKLanguage = tEnum(["javascript", "python", "java", "csharp"]); + scheme.DisposableInitializer = tOptional(tObject({})); + scheme.DisposableDisposeParams = tOptional(tObject({})); + scheme.DisposableDisposeResult = tOptional(tObject({})); + scheme.WaitInfo = tObject({ + waitId: tString, + phase: tEnum(["before", "after", "log"]), + event: tOptional(tString), + message: tOptional(tString), + error: tOptional(tString) + }); + scheme.ElectronInitializer = tOptional(tObject({})); + scheme.ElectronLaunchParams = tObject({ + executablePath: tOptional(tString), + args: tOptional(tArray(tString)), + chromiumSandbox: tOptional(tBoolean), + cwd: tOptional(tString), + env: tOptional(tArray(tType("NameValue"))), + timeout: tFloat, + acceptDownloads: tOptional(tEnum(["accept", "deny", "internal-browser-default"])), + bypassCSP: tOptional(tBoolean), + colorScheme: tOptional(tEnum(["dark", "light", "no-preference", "no-override"])), + extraHTTPHeaders: tOptional(tArray(tType("NameValue"))), + geolocation: tOptional(tObject({ + longitude: tFloat, + latitude: tFloat, + accuracy: tOptional(tFloat) + })), + httpCredentials: tOptional(tObject({ + username: tString, + password: tString, + origin: tOptional(tString) + })), + ignoreHTTPSErrors: tOptional(tBoolean), + locale: tOptional(tString), + offline: tOptional(tBoolean), + recordVideo: tOptional(tObject({ + dir: tOptional(tString), + size: tOptional(tObject({ + width: tInt, + height: tInt + })), + showActions: tOptional(tObject({ + duration: tOptional(tFloat), + position: tOptional(tEnum(["top-left", "top", "top-right", "bottom-left", "bottom", "bottom-right"])), + fontSize: tOptional(tInt), + cursor: tOptional(tEnum(["none", "pointer"])) + })) + })), + strictSelectors: tOptional(tBoolean), + timezoneId: tOptional(tString), + tracesDir: tOptional(tString), + artifactsDir: tOptional(tString), + selectorEngines: tOptional(tArray(tType("SelectorEngine"))), + testIdAttributeName: tOptional(tString) + }); + scheme.ElectronLaunchResult = tObject({ + electronApplication: tChannel(["ElectronApplication"]) + }); + scheme.ElectronApplicationInitializer = tObject({ + context: tChannel(["BrowserContext"]) + }); + scheme.ElectronApplicationCloseEvent = tOptional(tObject({})); + scheme.ElectronApplicationConsoleEvent = tObject({ + type: tString, + text: tString, + args: tArray(tChannel(["ElementHandle", "JSHandle"])), + location: tObject({ + url: tString, + lineNumber: tInt, + columnNumber: tInt + }), + timestamp: tFloat + }); + scheme.ElectronApplicationBrowserWindowParams = tObject({ + page: tChannel(["Page"]) + }); + scheme.ElectronApplicationBrowserWindowResult = tObject({ + handle: tChannel(["ElementHandle", "JSHandle"]) + }); + scheme.ElectronApplicationEvaluateExpressionParams = tObject({ + expression: tString, + isFunction: tOptional(tBoolean), + arg: tType("SerializedArgument") + }); + scheme.ElectronApplicationEvaluateExpressionResult = tObject({ + value: tType("SerializedValue") + }); + scheme.ElectronApplicationEvaluateExpressionHandleParams = tObject({ + expression: tString, + isFunction: tOptional(tBoolean), + arg: tType("SerializedArgument") + }); + scheme.ElectronApplicationEvaluateExpressionHandleResult = tObject({ + handle: tChannel(["ElementHandle", "JSHandle"]) + }); + scheme.ElectronApplicationUpdateSubscriptionParams = tObject({ + event: tEnum(["console"]), + enabled: tBoolean + }); + scheme.ElectronApplicationUpdateSubscriptionResult = tOptional(tObject({})); + scheme.FrameInitializer = tObject({ + url: tString, + name: tString, + parentFrame: tOptional(tChannel(["Frame"])), + loadStates: tArray(tType("LifecycleEvent")) + }); + scheme.FrameLoadstateEvent = tObject({ + add: tOptional(tType("LifecycleEvent")), + remove: tOptional(tType("LifecycleEvent")) + }); + scheme.FrameNavigatedEvent = tObject({ + url: tString, + name: tString, + newDocument: tOptional(tObject({ + request: tOptional(tChannel(["Request"])) + })), + error: tOptional(tString) + }); + scheme.FrameEvalOnSelectorParams = tObject({ + selector: tString, + strict: tOptional(tBoolean), + expression: tString, + isFunction: tOptional(tBoolean), + arg: tType("SerializedArgument") + }); + scheme.FrameEvalOnSelectorResult = tObject({ + value: tType("SerializedValue") + }); + scheme.FrameEvalOnSelectorAllParams = tObject({ + selector: tString, + expression: tString, + isFunction: tOptional(tBoolean), + arg: tType("SerializedArgument") + }); + scheme.FrameEvalOnSelectorAllResult = tObject({ + value: tType("SerializedValue") + }); + scheme.FrameAddScriptTagParams = tObject({ + url: tOptional(tString), + content: tOptional(tString), + type: tOptional(tString) + }); + scheme.FrameAddScriptTagResult = tObject({ + element: tChannel(["ElementHandle"]) + }); + scheme.FrameAddStyleTagParams = tObject({ + url: tOptional(tString), + content: tOptional(tString) + }); + scheme.FrameAddStyleTagResult = tObject({ + element: tChannel(["ElementHandle"]) + }); + scheme.FrameAriaSnapshotParams = tObject({ + mode: tOptional(tEnum(["ai", "default"])), + track: tOptional(tString), + selector: tOptional(tString), + depth: tOptional(tInt), + boxes: tOptional(tBoolean), + timeout: tFloat + }); + scheme.FrameAriaSnapshotResult = tObject({ + snapshot: tString + }); + scheme.FrameBlurParams = tObject({ + selector: tString, + strict: tOptional(tBoolean), + timeout: tFloat + }); + scheme.FrameBlurResult = tOptional(tObject({})); + scheme.FrameCheckParams = tObject({ + selector: tString, + strict: tOptional(tBoolean), + force: tOptional(tBoolean), + position: tOptional(tType("Point")), + timeout: tFloat, + trial: tOptional(tBoolean) + }); + scheme.FrameCheckResult = tOptional(tObject({})); + scheme.FrameClickParams = tObject({ + selector: tString, + strict: tOptional(tBoolean), + force: tOptional(tBoolean), + noWaitAfter: tOptional(tBoolean), + modifiers: tOptional(tArray(tEnum(["Alt", "Control", "ControlOrMeta", "Meta", "Shift"]))), + position: tOptional(tType("Point")), + delay: tOptional(tFloat), + button: tOptional(tEnum(["left", "right", "middle"])), + clickCount: tOptional(tInt), + timeout: tFloat, + trial: tOptional(tBoolean), + steps: tOptional(tInt) + }); + scheme.FrameClickResult = tOptional(tObject({})); + scheme.FrameContentParams = tOptional(tObject({})); + scheme.FrameContentResult = tObject({ + value: tString + }); + scheme.FrameDragAndDropParams = tObject({ + source: tString, + target: tString, + force: tOptional(tBoolean), + timeout: tFloat, + trial: tOptional(tBoolean), + sourcePosition: tOptional(tType("Point")), + targetPosition: tOptional(tType("Point")), + strict: tOptional(tBoolean), + steps: tOptional(tInt) + }); + scheme.FrameDragAndDropResult = tOptional(tObject({})); + scheme.FrameDropParams = tObject({ + selector: tString, + strict: tOptional(tBoolean), + position: tOptional(tType("Point")), + payloads: tOptional(tArray(tObject({ + name: tString, + mimeType: tOptional(tString), + buffer: tBinary + }))), + localPaths: tOptional(tArray(tString)), + streams: tOptional(tArray(tChannel(["WritableStream"]))), + data: tOptional(tArray(tObject({ + mimeType: tString, + value: tString + }))), + timeout: tFloat + }); + scheme.FrameDropResult = tOptional(tObject({})); + scheme.FrameDblclickParams = tObject({ + selector: tString, + strict: tOptional(tBoolean), + force: tOptional(tBoolean), + modifiers: tOptional(tArray(tEnum(["Alt", "Control", "ControlOrMeta", "Meta", "Shift"]))), + position: tOptional(tType("Point")), + delay: tOptional(tFloat), + button: tOptional(tEnum(["left", "right", "middle"])), + timeout: tFloat, + trial: tOptional(tBoolean), + steps: tOptional(tInt) + }); + scheme.FrameDblclickResult = tOptional(tObject({})); + scheme.FrameDispatchEventParams = tObject({ + selector: tString, + strict: tOptional(tBoolean), + type: tString, + eventInit: tType("SerializedArgument"), + timeout: tFloat + }); + scheme.FrameDispatchEventResult = tOptional(tObject({})); + scheme.FrameEvaluateExpressionParams = tObject({ + expression: tString, + isFunction: tOptional(tBoolean), + arg: tType("SerializedArgument") + }); + scheme.FrameEvaluateExpressionResult = tObject({ + value: tType("SerializedValue") + }); + scheme.FrameEvaluateExpressionHandleParams = tObject({ + expression: tString, + isFunction: tOptional(tBoolean), + arg: tType("SerializedArgument") + }); + scheme.FrameEvaluateExpressionHandleResult = tObject({ + handle: tChannel(["ElementHandle", "JSHandle"]) + }); + scheme.FrameFillParams = tObject({ + selector: tString, + strict: tOptional(tBoolean), + value: tString, + force: tOptional(tBoolean), + timeout: tFloat + }); + scheme.FrameFillResult = tOptional(tObject({})); + scheme.FrameFocusParams = tObject({ + selector: tString, + strict: tOptional(tBoolean), + timeout: tFloat + }); + scheme.FrameFocusResult = tOptional(tObject({})); + scheme.FrameFrameElementParams = tOptional(tObject({})); + scheme.FrameFrameElementResult = tObject({ + element: tChannel(["ElementHandle"]) + }); + scheme.FrameResolveSelectorParams = tObject({ + selector: tString + }); + scheme.FrameResolveSelectorResult = tObject({ + resolvedSelector: tString + }); + scheme.FrameHighlightParams = tObject({ + selector: tString, + style: tOptional(tString) + }); + scheme.FrameHighlightResult = tOptional(tObject({})); + scheme.FrameHideHighlightParams = tObject({ + selector: tString + }); + scheme.FrameHideHighlightResult = tOptional(tObject({})); + scheme.FrameGetAttributeParams = tObject({ + selector: tString, + strict: tOptional(tBoolean), + name: tString, + timeout: tFloat + }); + scheme.FrameGetAttributeResult = tObject({ + value: tOptional(tString) + }); + scheme.FrameGotoParams = tObject({ + url: tString, + timeout: tFloat, + waitUntil: tOptional(tType("LifecycleEvent")), + referer: tOptional(tString) + }); + scheme.FrameGotoResult = tObject({ + response: tOptional(tChannel(["Response"])) + }); + scheme.FrameHoverParams = tObject({ + selector: tString, + strict: tOptional(tBoolean), + force: tOptional(tBoolean), + modifiers: tOptional(tArray(tEnum(["Alt", "Control", "ControlOrMeta", "Meta", "Shift"]))), + position: tOptional(tType("Point")), + timeout: tFloat, + trial: tOptional(tBoolean) + }); + scheme.FrameHoverResult = tOptional(tObject({})); + scheme.FrameInnerHTMLParams = tObject({ + selector: tString, + strict: tOptional(tBoolean), + timeout: tFloat + }); + scheme.FrameInnerHTMLResult = tObject({ + value: tString + }); + scheme.FrameInnerTextParams = tObject({ + selector: tString, + strict: tOptional(tBoolean), + timeout: tFloat + }); + scheme.FrameInnerTextResult = tObject({ + value: tString + }); + scheme.FrameInputValueParams = tObject({ + selector: tString, + strict: tOptional(tBoolean), + timeout: tFloat + }); + scheme.FrameInputValueResult = tObject({ + value: tString + }); + scheme.FrameIsCheckedParams = tObject({ + selector: tString, + strict: tOptional(tBoolean), + timeout: tFloat + }); + scheme.FrameIsCheckedResult = tObject({ + value: tBoolean + }); + scheme.FrameIsDisabledParams = tObject({ + selector: tString, + strict: tOptional(tBoolean), + timeout: tFloat + }); + scheme.FrameIsDisabledResult = tObject({ + value: tBoolean + }); + scheme.FrameIsEnabledParams = tObject({ + selector: tString, + strict: tOptional(tBoolean), + timeout: tFloat + }); + scheme.FrameIsEnabledResult = tObject({ + value: tBoolean + }); + scheme.FrameIsHiddenParams = tObject({ + selector: tString, + strict: tOptional(tBoolean) + }); + scheme.FrameIsHiddenResult = tObject({ + value: tBoolean + }); + scheme.FrameIsVisibleParams = tObject({ + selector: tString, + strict: tOptional(tBoolean) + }); + scheme.FrameIsVisibleResult = tObject({ + value: tBoolean + }); + scheme.FrameIsEditableParams = tObject({ + selector: tString, + strict: tOptional(tBoolean), + timeout: tFloat + }); + scheme.FrameIsEditableResult = tObject({ + value: tBoolean + }); + scheme.FramePressParams = tObject({ + selector: tString, + strict: tOptional(tBoolean), + key: tString, + delay: tOptional(tFloat), + noWaitAfter: tOptional(tBoolean), + timeout: tFloat + }); + scheme.FramePressResult = tOptional(tObject({})); + scheme.FrameQuerySelectorParams = tObject({ + selector: tString, + strict: tOptional(tBoolean) + }); + scheme.FrameQuerySelectorResult = tObject({ + element: tOptional(tChannel(["ElementHandle"])) + }); + scheme.FrameQuerySelectorAllParams = tObject({ + selector: tString + }); + scheme.FrameQuerySelectorAllResult = tObject({ + elements: tArray(tChannel(["ElementHandle"])) + }); + scheme.FrameQueryCountParams = tObject({ + selector: tString + }); + scheme.FrameQueryCountResult = tObject({ + value: tInt + }); + scheme.FrameSelectOptionParams = tObject({ + selector: tString, + strict: tOptional(tBoolean), + elements: tOptional(tArray(tChannel(["ElementHandle"]))), + options: tOptional(tArray(tObject({ + valueOrLabel: tOptional(tString), + value: tOptional(tString), + label: tOptional(tString), + index: tOptional(tInt) + }))), + force: tOptional(tBoolean), + timeout: tFloat + }); + scheme.FrameSelectOptionResult = tObject({ + values: tArray(tString) + }); + scheme.FrameSetContentParams = tObject({ + html: tString, + timeout: tFloat, + waitUntil: tOptional(tType("LifecycleEvent")) + }); + scheme.FrameSetContentResult = tOptional(tObject({})); + scheme.FrameSetInputFilesParams = tObject({ + selector: tString, + strict: tOptional(tBoolean), + payloads: tOptional(tArray(tObject({ + name: tString, + mimeType: tOptional(tString), + buffer: tBinary + }))), + localDirectory: tOptional(tString), + directoryStream: tOptional(tChannel(["WritableStream"])), + localPaths: tOptional(tArray(tString)), + streams: tOptional(tArray(tChannel(["WritableStream"]))), + timeout: tFloat + }); + scheme.FrameSetInputFilesResult = tOptional(tObject({})); + scheme.FrameTapParams = tObject({ + selector: tString, + strict: tOptional(tBoolean), + force: tOptional(tBoolean), + modifiers: tOptional(tArray(tEnum(["Alt", "Control", "ControlOrMeta", "Meta", "Shift"]))), + position: tOptional(tType("Point")), + timeout: tFloat, + trial: tOptional(tBoolean) + }); + scheme.FrameTapResult = tOptional(tObject({})); + scheme.FrameTextContentParams = tObject({ + selector: tString, + strict: tOptional(tBoolean), + timeout: tFloat + }); + scheme.FrameTextContentResult = tObject({ + value: tOptional(tString) + }); + scheme.FrameTitleParams = tOptional(tObject({})); + scheme.FrameTitleResult = tObject({ + value: tString + }); + scheme.FrameTypeParams = tObject({ + selector: tString, + strict: tOptional(tBoolean), + text: tString, + delay: tOptional(tFloat), + timeout: tFloat + }); + scheme.FrameTypeResult = tOptional(tObject({})); + scheme.FrameUncheckParams = tObject({ + selector: tString, + strict: tOptional(tBoolean), + force: tOptional(tBoolean), + position: tOptional(tType("Point")), + timeout: tFloat, + trial: tOptional(tBoolean) + }); + scheme.FrameUncheckResult = tOptional(tObject({})); + scheme.FrameWaitForTimeoutParams = tObject({ + waitTimeout: tFloat + }); + scheme.FrameWaitForTimeoutResult = tOptional(tObject({})); + scheme.FrameWaitForFunctionParams = tObject({ + expression: tString, + isFunction: tOptional(tBoolean), + arg: tType("SerializedArgument"), + timeout: tFloat, + pollingInterval: tOptional(tFloat) + }); + scheme.FrameWaitForFunctionResult = tObject({ + handle: tChannel(["ElementHandle", "JSHandle"]) + }); + scheme.FrameWaitForSelectorParams = tObject({ + selector: tString, + strict: tOptional(tBoolean), + timeout: tFloat, + state: tOptional(tEnum(["attached", "detached", "visible", "hidden"])), + omitReturnValue: tOptional(tBoolean) + }); + scheme.FrameWaitForSelectorResult = tObject({ + element: tOptional(tChannel(["ElementHandle"])) + }); + scheme.FrameExpectParams = tObject({ + selector: tOptional(tString), + expression: tString, + expressionArg: tOptional(tAny), + pseudo: tOptional(tEnum(["before", "after"])), + expectedText: tOptional(tArray(tType("ExpectedTextValue"))), + expectedNumber: tOptional(tFloat), + expectedValue: tOptional(tType("SerializedArgument")), + useInnerText: tOptional(tBoolean), + isNot: tBoolean, + timeout: tFloat + }); + scheme.FrameExpectResult = tOptional(tObject({})); + scheme.FrameExpectErrorDetails = tObject({ + received: tOptional(tObject({ + value: tOptional(tType("SerializedValue")), + ariaSnapshot: tOptional(tString) + })), + timedOut: tOptional(tBoolean), + customErrorMessage: tOptional(tString) + }); + scheme.JSHandleInitializer = tObject({ + preview: tString + }); + scheme.JSHandlePreviewUpdatedEvent = tObject({ + preview: tString + }); + scheme.ElementHandlePreviewUpdatedEvent = tType("JSHandlePreviewUpdatedEvent"); + scheme.JSHandleDisposeParams = tOptional(tObject({})); + scheme.ElementHandleDisposeParams = tType("JSHandleDisposeParams"); + scheme.JSHandleDisposeResult = tOptional(tObject({})); + scheme.ElementHandleDisposeResult = tType("JSHandleDisposeResult"); + scheme.JSHandleEvaluateExpressionParams = tObject({ + expression: tString, + isFunction: tOptional(tBoolean), + arg: tType("SerializedArgument") + }); + scheme.ElementHandleEvaluateExpressionParams = tType("JSHandleEvaluateExpressionParams"); + scheme.JSHandleEvaluateExpressionResult = tObject({ + value: tType("SerializedValue") + }); + scheme.ElementHandleEvaluateExpressionResult = tType("JSHandleEvaluateExpressionResult"); + scheme.JSHandleEvaluateExpressionHandleParams = tObject({ + expression: tString, + isFunction: tOptional(tBoolean), + arg: tType("SerializedArgument") + }); + scheme.ElementHandleEvaluateExpressionHandleParams = tType("JSHandleEvaluateExpressionHandleParams"); + scheme.JSHandleEvaluateExpressionHandleResult = tObject({ + handle: tChannel(["ElementHandle", "JSHandle"]) + }); + scheme.ElementHandleEvaluateExpressionHandleResult = tType("JSHandleEvaluateExpressionHandleResult"); + scheme.JSHandleGetPropertyListParams = tOptional(tObject({})); + scheme.ElementHandleGetPropertyListParams = tType("JSHandleGetPropertyListParams"); + scheme.JSHandleGetPropertyListResult = tObject({ + properties: tArray(tObject({ + name: tString, + value: tChannel(["ElementHandle", "JSHandle"]) + })) + }); + scheme.ElementHandleGetPropertyListResult = tType("JSHandleGetPropertyListResult"); + scheme.JSHandleGetPropertyParams = tObject({ + name: tString + }); + scheme.ElementHandleGetPropertyParams = tType("JSHandleGetPropertyParams"); + scheme.JSHandleGetPropertyResult = tObject({ + handle: tChannel(["ElementHandle", "JSHandle"]) + }); + scheme.ElementHandleGetPropertyResult = tType("JSHandleGetPropertyResult"); + scheme.JSHandleJsonValueParams = tOptional(tObject({})); + scheme.ElementHandleJsonValueParams = tType("JSHandleJsonValueParams"); + scheme.JSHandleJsonValueResult = tObject({ + value: tType("SerializedValue") + }); + scheme.ElementHandleJsonValueResult = tType("JSHandleJsonValueResult"); + scheme.ElementHandleInitializer = tObject({ + preview: tString + }); + scheme.ElementHandleEvalOnSelectorParams = tObject({ + selector: tString, + strict: tOptional(tBoolean), + expression: tString, + isFunction: tOptional(tBoolean), + arg: tType("SerializedArgument") + }); + scheme.ElementHandleEvalOnSelectorResult = tObject({ + value: tType("SerializedValue") + }); + scheme.ElementHandleEvalOnSelectorAllParams = tObject({ + selector: tString, + expression: tString, + isFunction: tOptional(tBoolean), + arg: tType("SerializedArgument") + }); + scheme.ElementHandleEvalOnSelectorAllResult = tObject({ + value: tType("SerializedValue") + }); + scheme.ElementHandleBoundingBoxParams = tOptional(tObject({})); + scheme.ElementHandleBoundingBoxResult = tObject({ + value: tOptional(tType("Rect")) + }); + scheme.ElementHandleCheckParams = tObject({ + force: tOptional(tBoolean), + position: tOptional(tType("Point")), + timeout: tFloat, + trial: tOptional(tBoolean) + }); + scheme.ElementHandleCheckResult = tOptional(tObject({})); + scheme.ElementHandleClickParams = tObject({ + force: tOptional(tBoolean), + noWaitAfter: tOptional(tBoolean), + modifiers: tOptional(tArray(tEnum(["Alt", "Control", "ControlOrMeta", "Meta", "Shift"]))), + position: tOptional(tType("Point")), + delay: tOptional(tFloat), + button: tOptional(tEnum(["left", "right", "middle"])), + clickCount: tOptional(tInt), + timeout: tFloat, + trial: tOptional(tBoolean), + steps: tOptional(tInt) + }); + scheme.ElementHandleClickResult = tOptional(tObject({})); + scheme.ElementHandleContentFrameParams = tOptional(tObject({})); + scheme.ElementHandleContentFrameResult = tObject({ + frame: tOptional(tChannel(["Frame"])) + }); + scheme.ElementHandleDblclickParams = tObject({ + force: tOptional(tBoolean), + modifiers: tOptional(tArray(tEnum(["Alt", "Control", "ControlOrMeta", "Meta", "Shift"]))), + position: tOptional(tType("Point")), + delay: tOptional(tFloat), + button: tOptional(tEnum(["left", "right", "middle"])), + timeout: tFloat, + trial: tOptional(tBoolean), + steps: tOptional(tInt) + }); + scheme.ElementHandleDblclickResult = tOptional(tObject({})); + scheme.ElementHandleDispatchEventParams = tObject({ + type: tString, + eventInit: tType("SerializedArgument") + }); + scheme.ElementHandleDispatchEventResult = tOptional(tObject({})); + scheme.ElementHandleFillParams = tObject({ + value: tString, + force: tOptional(tBoolean), + timeout: tFloat + }); + scheme.ElementHandleFillResult = tOptional(tObject({})); + scheme.ElementHandleFocusParams = tOptional(tObject({})); + scheme.ElementHandleFocusResult = tOptional(tObject({})); + scheme.ElementHandleGetAttributeParams = tObject({ + name: tString + }); + scheme.ElementHandleGetAttributeResult = tObject({ + value: tOptional(tString) + }); + scheme.ElementHandleHoverParams = tObject({ + force: tOptional(tBoolean), + modifiers: tOptional(tArray(tEnum(["Alt", "Control", "ControlOrMeta", "Meta", "Shift"]))), + position: tOptional(tType("Point")), + timeout: tFloat, + trial: tOptional(tBoolean) + }); + scheme.ElementHandleHoverResult = tOptional(tObject({})); + scheme.ElementHandleInnerHTMLParams = tOptional(tObject({})); + scheme.ElementHandleInnerHTMLResult = tObject({ + value: tString + }); + scheme.ElementHandleInnerTextParams = tOptional(tObject({})); + scheme.ElementHandleInnerTextResult = tObject({ + value: tString + }); + scheme.ElementHandleInputValueParams = tOptional(tObject({})); + scheme.ElementHandleInputValueResult = tObject({ + value: tString + }); + scheme.ElementHandleIsCheckedParams = tOptional(tObject({})); + scheme.ElementHandleIsCheckedResult = tObject({ + value: tBoolean + }); + scheme.ElementHandleIsDisabledParams = tOptional(tObject({})); + scheme.ElementHandleIsDisabledResult = tObject({ + value: tBoolean + }); + scheme.ElementHandleIsEditableParams = tOptional(tObject({})); + scheme.ElementHandleIsEditableResult = tObject({ + value: tBoolean + }); + scheme.ElementHandleIsEnabledParams = tOptional(tObject({})); + scheme.ElementHandleIsEnabledResult = tObject({ + value: tBoolean + }); + scheme.ElementHandleIsHiddenParams = tOptional(tObject({})); + scheme.ElementHandleIsHiddenResult = tObject({ + value: tBoolean + }); + scheme.ElementHandleIsVisibleParams = tOptional(tObject({})); + scheme.ElementHandleIsVisibleResult = tObject({ + value: tBoolean + }); + scheme.ElementHandleOwnerFrameParams = tOptional(tObject({})); + scheme.ElementHandleOwnerFrameResult = tObject({ + frame: tOptional(tChannel(["Frame"])) + }); + scheme.ElementHandlePressParams = tObject({ + key: tString, + delay: tOptional(tFloat), + timeout: tFloat, + noWaitAfter: tOptional(tBoolean) + }); + scheme.ElementHandlePressResult = tOptional(tObject({})); + scheme.ElementHandleQuerySelectorParams = tObject({ + selector: tString, + strict: tOptional(tBoolean) + }); + scheme.ElementHandleQuerySelectorResult = tObject({ + element: tOptional(tChannel(["ElementHandle"])) + }); + scheme.ElementHandleQuerySelectorAllParams = tObject({ + selector: tString + }); + scheme.ElementHandleQuerySelectorAllResult = tObject({ + elements: tArray(tChannel(["ElementHandle"])) + }); + scheme.ElementHandleScreenshotParams = tObject({ + timeout: tFloat, + type: tOptional(tEnum(["png", "jpeg"])), + quality: tOptional(tInt), + omitBackground: tOptional(tBoolean), + caret: tOptional(tEnum(["hide", "initial"])), + animations: tOptional(tEnum(["disabled", "allow"])), + scale: tOptional(tEnum(["css", "device"])), + mask: tOptional(tArray(tObject({ + frame: tChannel(["Frame"]), + selector: tString + }))), + maskColor: tOptional(tString), + style: tOptional(tString) + }); + scheme.ElementHandleScreenshotResult = tObject({ + binary: tBinary + }); + scheme.ElementHandleScrollIntoViewIfNeededParams = tObject({ + timeout: tFloat + }); + scheme.ElementHandleScrollIntoViewIfNeededResult = tOptional(tObject({})); + scheme.ElementHandleSelectOptionParams = tObject({ + elements: tOptional(tArray(tChannel(["ElementHandle"]))), + options: tOptional(tArray(tObject({ + valueOrLabel: tOptional(tString), + value: tOptional(tString), + label: tOptional(tString), + index: tOptional(tInt) + }))), + force: tOptional(tBoolean), + timeout: tFloat + }); + scheme.ElementHandleSelectOptionResult = tObject({ + values: tArray(tString) + }); + scheme.ElementHandleSelectTextParams = tObject({ + force: tOptional(tBoolean), + timeout: tFloat + }); + scheme.ElementHandleSelectTextResult = tOptional(tObject({})); + scheme.ElementHandleSetInputFilesParams = tObject({ + payloads: tOptional(tArray(tObject({ + name: tString, + mimeType: tOptional(tString), + buffer: tBinary + }))), + localDirectory: tOptional(tString), + directoryStream: tOptional(tChannel(["WritableStream"])), + localPaths: tOptional(tArray(tString)), + streams: tOptional(tArray(tChannel(["WritableStream"]))), + timeout: tFloat + }); + scheme.ElementHandleSetInputFilesResult = tOptional(tObject({})); + scheme.ElementHandleTapParams = tObject({ + force: tOptional(tBoolean), + modifiers: tOptional(tArray(tEnum(["Alt", "Control", "ControlOrMeta", "Meta", "Shift"]))), + position: tOptional(tType("Point")), + timeout: tFloat, + trial: tOptional(tBoolean) + }); + scheme.ElementHandleTapResult = tOptional(tObject({})); + scheme.ElementHandleTextContentParams = tOptional(tObject({})); + scheme.ElementHandleTextContentResult = tObject({ + value: tOptional(tString) + }); + scheme.ElementHandleTypeParams = tObject({ + text: tString, + delay: tOptional(tFloat), + timeout: tFloat + }); + scheme.ElementHandleTypeResult = tOptional(tObject({})); + scheme.ElementHandleUncheckParams = tObject({ + force: tOptional(tBoolean), + position: tOptional(tType("Point")), + timeout: tFloat, + trial: tOptional(tBoolean) + }); + scheme.ElementHandleUncheckResult = tOptional(tObject({})); + scheme.ElementHandleWaitForElementStateParams = tObject({ + state: tEnum(["visible", "hidden", "stable", "enabled", "disabled", "editable"]), + timeout: tFloat + }); + scheme.ElementHandleWaitForElementStateResult = tOptional(tObject({})); + scheme.ElementHandleWaitForSelectorParams = tObject({ + selector: tString, + strict: tOptional(tBoolean), + timeout: tFloat, + state: tOptional(tEnum(["attached", "detached", "visible", "hidden"])) + }); + scheme.ElementHandleWaitForSelectorResult = tObject({ + element: tOptional(tChannel(["ElementHandle"])) + }); + scheme.LocalUtilsInitializer = tObject({ + deviceDescriptors: tArray(tObject({ + name: tString, + descriptor: tObject({ + userAgent: tString, + viewport: tObject({ + width: tInt, + height: tInt + }), + screen: tOptional(tObject({ + width: tInt, + height: tInt + })), + deviceScaleFactor: tFloat, + isMobile: tBoolean, + hasTouch: tBoolean, + defaultBrowserType: tEnum(["chromium", "firefox", "webkit"]) + }) + })) + }); + scheme.LocalUtilsZipParams = tObject({ + zipFile: tString, + entries: tArray(tType("NameValue")), + stacksId: tOptional(tString), + mode: tEnum(["write", "append"]), + includeSources: tBoolean, + additionalSources: tOptional(tArray(tString)) + }); + scheme.LocalUtilsZipResult = tOptional(tObject({})); + scheme.LocalUtilsHarOpenParams = tObject({ + file: tString + }); + scheme.LocalUtilsHarOpenResult = tObject({ + harId: tOptional(tString), + error: tOptional(tString) + }); + scheme.LocalUtilsHarLookupParams = tObject({ + harId: tString, + url: tString, + method: tString, + headers: tArray(tType("NameValue")), + postData: tOptional(tBinary), + isNavigationRequest: tBoolean + }); + scheme.LocalUtilsHarLookupResult = tObject({ + action: tEnum(["error", "redirect", "fulfill", "noentry"]), + message: tOptional(tString), + redirectURL: tOptional(tString), + status: tOptional(tInt), + headers: tOptional(tArray(tType("NameValue"))), + body: tOptional(tBinary) + }); + scheme.LocalUtilsHarCloseParams = tObject({ + harId: tString + }); + scheme.LocalUtilsHarCloseResult = tOptional(tObject({})); + scheme.LocalUtilsHarUnzipParams = tObject({ + zipFile: tString, + harFile: tString, + resourcesDir: tOptional(tString) + }); + scheme.LocalUtilsHarUnzipResult = tOptional(tObject({})); + scheme.LocalUtilsConnectParams = tObject({ + endpoint: tString, + headers: tOptional(tAny), + exposeNetwork: tOptional(tString), + slowMo: tOptional(tFloat), + timeout: tFloat, + socksProxyRedirectPortForTest: tOptional(tInt) + }); + scheme.LocalUtilsConnectResult = tObject({ + pipe: tChannel(["JsonPipe"]), + headers: tArray(tType("NameValue")) + }); + scheme.LocalUtilsTracingStartedParams = tObject({ + tracesDir: tOptional(tString), + traceName: tString, + live: tOptional(tBoolean) + }); + scheme.LocalUtilsTracingStartedResult = tObject({ + stacksId: tString + }); + scheme.LocalUtilsAddStackToTracingNoReplyParams = tObject({ + callData: tType("ClientSideCallMetadata") + }); + scheme.LocalUtilsAddStackToTracingNoReplyResult = tOptional(tObject({})); + scheme.LocalUtilsTraceDiscardedParams = tObject({ + stacksId: tString + }); + scheme.LocalUtilsTraceDiscardedResult = tOptional(tObject({})); + scheme.LocalUtilsGlobToRegexParams = tObject({ + glob: tString, + baseURL: tOptional(tString), + webSocketUrl: tOptional(tBoolean) + }); + scheme.LocalUtilsGlobToRegexResult = tObject({ + regex: tString + }); + scheme.SetNetworkCookie = tObject({ + name: tString, + value: tString, + url: tOptional(tString), + domain: tOptional(tString), + path: tOptional(tString), + expires: tOptional(tFloat), + httpOnly: tOptional(tBoolean), + secure: tOptional(tBoolean), + sameSite: tOptional(tEnum(["Strict", "Lax", "None"])), + partitionKey: tOptional(tString), + _crHasCrossSiteAncestor: tOptional(tBoolean) + }); + scheme.NetworkCookie = tObject({ + name: tString, + value: tString, + domain: tString, + path: tString, + expires: tFloat, + httpOnly: tBoolean, + secure: tBoolean, + sameSite: tEnum(["Strict", "Lax", "None"]), + partitionKey: tOptional(tString), + _crHasCrossSiteAncestor: tOptional(tBoolean) + }); + scheme.RequestInitializer = tObject({ + frame: tOptional(tChannel(["Frame"])), + serviceWorker: tOptional(tChannel(["Worker"])), + url: tString, + resourceType: tString, + method: tString, + postData: tOptional(tBinary), + headers: tArray(tType("NameValue")), + isNavigationRequest: tBoolean, + redirectedFrom: tOptional(tChannel(["Request"])) + }); + scheme.RequestResponseParams = tOptional(tObject({})); + scheme.RequestResponseResult = tObject({ + response: tOptional(tChannel(["Response"])) + }); + scheme.RequestRawRequestHeadersParams = tOptional(tObject({})); + scheme.RequestRawRequestHeadersResult = tObject({ + headers: tArray(tType("NameValue")) + }); + scheme.RouteInitializer = tObject({ + request: tChannel(["Request"]) + }); + scheme.RouteRedirectNavigationRequestParams = tObject({ + url: tString + }); + scheme.RouteRedirectNavigationRequestResult = tOptional(tObject({})); + scheme.RouteAbortParams = tObject({ + errorCode: tOptional(tString) + }); + scheme.RouteAbortResult = tOptional(tObject({})); + scheme.RouteContinueParams = tObject({ + url: tOptional(tString), + method: tOptional(tString), + headers: tOptional(tArray(tType("NameValue"))), + postData: tOptional(tBinary), + isFallback: tBoolean + }); + scheme.RouteContinueResult = tOptional(tObject({})); + scheme.RouteFulfillParams = tObject({ + status: tOptional(tInt), + headers: tOptional(tArray(tType("NameValue"))), + body: tOptional(tString), + isBase64: tOptional(tBoolean), + fetchResponseUid: tOptional(tString) + }); + scheme.RouteFulfillResult = tOptional(tObject({})); + scheme.WebSocketRouteInitializer = tObject({ + url: tString, + protocols: tArray(tString) + }); + scheme.WebSocketRouteMessageFromPageEvent = tObject({ + message: tString, + isBase64: tBoolean + }); + scheme.WebSocketRouteMessageFromServerEvent = tObject({ + message: tString, + isBase64: tBoolean + }); + scheme.WebSocketRouteClosePageEvent = tObject({ + code: tOptional(tInt), + reason: tOptional(tString), + wasClean: tBoolean + }); + scheme.WebSocketRouteCloseServerEvent = tObject({ + code: tOptional(tInt), + reason: tOptional(tString), + wasClean: tBoolean + }); + scheme.WebSocketRouteConnectParams = tOptional(tObject({})); + scheme.WebSocketRouteConnectResult = tOptional(tObject({})); + scheme.WebSocketRouteEnsureOpenedParams = tOptional(tObject({})); + scheme.WebSocketRouteEnsureOpenedResult = tOptional(tObject({})); + scheme.WebSocketRouteSendToPageParams = tObject({ + message: tString, + isBase64: tBoolean + }); + scheme.WebSocketRouteSendToPageResult = tOptional(tObject({})); + scheme.WebSocketRouteSendToServerParams = tObject({ + message: tString, + isBase64: tBoolean + }); + scheme.WebSocketRouteSendToServerResult = tOptional(tObject({})); + scheme.WebSocketRouteClosePageParams = tObject({ + code: tOptional(tInt), + reason: tOptional(tString), + wasClean: tBoolean + }); + scheme.WebSocketRouteClosePageResult = tOptional(tObject({})); + scheme.WebSocketRouteCloseServerParams = tObject({ + code: tOptional(tInt), + reason: tOptional(tString), + wasClean: tBoolean + }); + scheme.WebSocketRouteCloseServerResult = tOptional(tObject({})); + scheme.ResourceTiming = tObject({ + startTime: tFloat, + domainLookupStart: tFloat, + domainLookupEnd: tFloat, + connectStart: tFloat, + secureConnectionStart: tFloat, + connectEnd: tFloat, + requestStart: tFloat, + responseStart: tFloat + }); + scheme.ResponseInitializer = tObject({ + request: tChannel(["Request"]), + url: tString, + status: tInt, + statusText: tString, + headers: tArray(tType("NameValue")), + timing: tType("ResourceTiming"), + fromServiceWorker: tBoolean + }); + scheme.ResponseBodyParams = tOptional(tObject({})); + scheme.ResponseBodyResult = tObject({ + binary: tBinary + }); + scheme.ResponseSecurityDetailsParams = tOptional(tObject({})); + scheme.ResponseSecurityDetailsResult = tObject({ + value: tOptional(tType("SecurityDetails")) + }); + scheme.ResponseServerAddrParams = tOptional(tObject({})); + scheme.ResponseServerAddrResult = tObject({ + value: tOptional(tType("RemoteAddr")) + }); + scheme.ResponseRawResponseHeadersParams = tOptional(tObject({})); + scheme.ResponseRawResponseHeadersResult = tObject({ + headers: tArray(tType("NameValue")) + }); + scheme.ResponseHttpVersionParams = tOptional(tObject({})); + scheme.ResponseHttpVersionResult = tObject({ + value: tString + }); + scheme.ResponseSizesParams = tOptional(tObject({})); + scheme.ResponseSizesResult = tObject({ + sizes: tType("RequestSizes") + }); + scheme.SecurityDetails = tObject({ + issuer: tOptional(tString), + protocol: tOptional(tString), + subjectName: tOptional(tString), + validFrom: tOptional(tFloat), + validTo: tOptional(tFloat) + }); + scheme.RequestSizes = tObject({ + requestBodySize: tInt, + requestHeadersSize: tInt, + responseBodySize: tInt, + responseHeadersSize: tInt + }); + scheme.RemoteAddr = tObject({ + ipAddress: tString, + port: tInt + }); + scheme.WebSocketInitializer = tObject({ + url: tString + }); + scheme.WebSocketOpenEvent = tOptional(tObject({})); + scheme.WebSocketFrameSentEvent = tObject({ + opcode: tInt, + data: tString + }); + scheme.WebSocketFrameReceivedEvent = tObject({ + opcode: tInt, + data: tString + }); + scheme.WebSocketSocketErrorEvent = tObject({ + error: tString + }); + scheme.WebSocketCloseEvent = tOptional(tObject({})); + scheme.PageInitializer = tObject({ + mainFrame: tChannel(["Frame"]), + viewportSize: tOptional(tObject({ + width: tInt, + height: tInt + })), + isClosed: tBoolean, + opener: tOptional(tChannel(["Page"])), + video: tOptional(tChannel(["Artifact"])) + }); + scheme.PageBindingCallEvent = tObject({ + binding: tChannel(["BindingCall"]) + }); + scheme.PageCloseEvent = tOptional(tObject({})); + scheme.PageCrashEvent = tOptional(tObject({})); + scheme.PageDownloadEvent = tObject({ + url: tString, + suggestedFilename: tString, + artifact: tChannel(["Artifact"]) + }); + scheme.PageViewportSizeChangedEvent = tObject({ + viewportSize: tOptional(tObject({ + width: tInt, + height: tInt + })) + }); + scheme.PageFileChooserEvent = tObject({ + element: tChannel(["ElementHandle"]), + isMultiple: tBoolean + }); + scheme.PageFrameAttachedEvent = tObject({ + frame: tChannel(["Frame"]) + }); + scheme.PageFrameDetachedEvent = tObject({ + frame: tChannel(["Frame"]) + }); + scheme.PageLocatorHandlerTriggeredEvent = tObject({ + uid: tInt + }); + scheme.PageRouteEvent = tObject({ + route: tChannel(["Route"]) + }); + scheme.PageScreencastFrameEvent = tObject({ + data: tBinary, + timestamp: tFloat, + viewportWidth: tInt, + viewportHeight: tInt + }); + scheme.PageWebSocketRouteEvent = tObject({ + webSocketRoute: tChannel(["WebSocketRoute"]) + }); + scheme.PageWebSocketEvent = tObject({ + webSocket: tChannel(["WebSocket"]) + }); + scheme.PageWorkerEvent = tObject({ + worker: tChannel(["Worker"]) + }); + scheme.PageAddInitScriptParams = tObject({ + source: tString + }); + scheme.PageAddInitScriptResult = tObject({ + disposable: tChannel(["Disposable"]) + }); + scheme.PageCloseParams = tObject({ + reason: tOptional(tString) + }); + scheme.PageCloseResult = tOptional(tObject({})); + scheme.PageRunBeforeUnloadParams = tOptional(tObject({})); + scheme.PageRunBeforeUnloadResult = tOptional(tObject({})); + scheme.PageClearConsoleMessagesParams = tOptional(tObject({})); + scheme.PageClearConsoleMessagesResult = tOptional(tObject({})); + scheme.PageConsoleMessagesParams = tObject({ + filter: tOptional(tType("ConsoleMessagesFilter")) + }); + scheme.PageConsoleMessagesResult = tObject({ + messages: tArray(tObject({ + type: tString, + text: tString, + args: tArray(tChannel(["ElementHandle", "JSHandle"])), + location: tObject({ + url: tString, + lineNumber: tInt, + columnNumber: tInt + }), + timestamp: tFloat + })) + }); + scheme.PageEmulateMediaParams = tObject({ + media: tOptional(tEnum(["screen", "print", "no-override"])), + colorScheme: tOptional(tEnum(["dark", "light", "no-preference", "no-override"])), + reducedMotion: tOptional(tEnum(["reduce", "no-preference", "no-override"])), + forcedColors: tOptional(tEnum(["active", "none", "no-override"])), + contrast: tOptional(tEnum(["no-preference", "more", "no-override"])) + }); + scheme.PageEmulateMediaResult = tOptional(tObject({})); + scheme.PageExposeBindingParams = tObject({ + name: tString + }); + scheme.PageExposeBindingResult = tObject({ + disposable: tChannel(["Disposable"]) + }); + scheme.PageGoBackParams = tObject({ + timeout: tFloat, + waitUntil: tOptional(tType("LifecycleEvent")) + }); + scheme.PageGoBackResult = tObject({ + response: tOptional(tChannel(["Response"])) + }); + scheme.PageGoForwardParams = tObject({ + timeout: tFloat, + waitUntil: tOptional(tType("LifecycleEvent")) + }); + scheme.PageGoForwardResult = tObject({ + response: tOptional(tChannel(["Response"])) + }); + scheme.PageRequestGCParams = tOptional(tObject({})); + scheme.PageRequestGCResult = tOptional(tObject({})); + scheme.PageRegisterLocatorHandlerParams = tObject({ + selector: tString, + noWaitAfter: tOptional(tBoolean) + }); + scheme.PageRegisterLocatorHandlerResult = tObject({ + uid: tInt + }); + scheme.PageResolveLocatorHandlerNoReplyParams = tObject({ + uid: tInt, + remove: tOptional(tBoolean) + }); + scheme.PageResolveLocatorHandlerNoReplyResult = tOptional(tObject({})); + scheme.PageUnregisterLocatorHandlerParams = tObject({ + uid: tInt + }); + scheme.PageUnregisterLocatorHandlerResult = tOptional(tObject({})); + scheme.PageReloadParams = tObject({ + timeout: tFloat, + waitUntil: tOptional(tType("LifecycleEvent")) + }); + scheme.PageReloadResult = tObject({ + response: tOptional(tChannel(["Response"])) + }); + scheme.PageExpectScreenshotParams = tObject({ + expected: tOptional(tBinary), + timeout: tFloat, + isNot: tBoolean, + locator: tOptional(tObject({ + frame: tChannel(["Frame"]), + selector: tString + })), + comparator: tOptional(tString), + maxDiffPixels: tOptional(tInt), + maxDiffPixelRatio: tOptional(tFloat), + threshold: tOptional(tFloat), + fullPage: tOptional(tBoolean), + clip: tOptional(tType("Rect")), + omitBackground: tOptional(tBoolean), + caret: tOptional(tEnum(["hide", "initial"])), + animations: tOptional(tEnum(["disabled", "allow"])), + scale: tOptional(tEnum(["css", "device"])), + mask: tOptional(tArray(tObject({ + frame: tChannel(["Frame"]), + selector: tString + }))), + maskColor: tOptional(tString), + style: tOptional(tString) + }); + scheme.PageExpectScreenshotResult = tObject({ + actual: tOptional(tBinary) + }); + scheme.PageExpectScreenshotErrorDetails = tObject({ + diff: tOptional(tBinary), + customErrorMessage: tOptional(tString), + actual: tOptional(tBinary), + previous: tOptional(tBinary), + timedOut: tOptional(tBoolean), + log: tOptional(tArray(tString)) + }); + scheme.PageScreenshotParams = tObject({ + timeout: tFloat, + type: tOptional(tEnum(["png", "jpeg"])), + quality: tOptional(tInt), + fullPage: tOptional(tBoolean), + clip: tOptional(tType("Rect")), + omitBackground: tOptional(tBoolean), + caret: tOptional(tEnum(["hide", "initial"])), + animations: tOptional(tEnum(["disabled", "allow"])), + scale: tOptional(tEnum(["css", "device"])), + mask: tOptional(tArray(tObject({ + frame: tChannel(["Frame"]), + selector: tString + }))), + maskColor: tOptional(tString), + style: tOptional(tString) + }); + scheme.PageScreenshotResult = tObject({ + binary: tBinary + }); + scheme.PageSetExtraHTTPHeadersParams = tObject({ + headers: tArray(tType("NameValue")) + }); + scheme.PageSetExtraHTTPHeadersResult = tOptional(tObject({})); + scheme.PageSetNetworkInterceptionPatternsParams = tObject({ + patterns: tArray(tObject({ + glob: tOptional(tString), + regexSource: tOptional(tString), + regexFlags: tOptional(tString), + urlPattern: tOptional(tType("URLPattern")) + })) + }); + scheme.PageSetNetworkInterceptionPatternsResult = tOptional(tObject({})); + scheme.PageSetWebSocketInterceptionPatternsParams = tObject({ + patterns: tArray(tObject({ + glob: tOptional(tString), + regexSource: tOptional(tString), + regexFlags: tOptional(tString), + urlPattern: tOptional(tType("URLPattern")) + })) + }); + scheme.PageSetWebSocketInterceptionPatternsResult = tOptional(tObject({})); + scheme.PageSetViewportSizeParams = tObject({ + viewportSize: tObject({ + width: tInt, + height: tInt + }) + }); + scheme.PageSetViewportSizeResult = tOptional(tObject({})); + scheme.PageKeyboardDownParams = tObject({ + key: tString + }); + scheme.PageKeyboardDownResult = tOptional(tObject({})); + scheme.PageKeyboardUpParams = tObject({ + key: tString + }); + scheme.PageKeyboardUpResult = tOptional(tObject({})); + scheme.PageKeyboardInsertTextParams = tObject({ + text: tString + }); + scheme.PageKeyboardInsertTextResult = tOptional(tObject({})); + scheme.PageKeyboardTypeParams = tObject({ + text: tString, + delay: tOptional(tFloat) + }); + scheme.PageKeyboardTypeResult = tOptional(tObject({})); + scheme.PageKeyboardPressParams = tObject({ + key: tString, + delay: tOptional(tFloat) + }); + scheme.PageKeyboardPressResult = tOptional(tObject({})); + scheme.PageMouseMoveParams = tObject({ + x: tFloat, + y: tFloat, + steps: tOptional(tInt) + }); + scheme.PageMouseMoveResult = tOptional(tObject({})); + scheme.PageMouseDownParams = tObject({ + button: tOptional(tEnum(["left", "right", "middle"])), + clickCount: tOptional(tInt) + }); + scheme.PageMouseDownResult = tOptional(tObject({})); + scheme.PageMouseUpParams = tObject({ + button: tOptional(tEnum(["left", "right", "middle"])), + clickCount: tOptional(tInt) + }); + scheme.PageMouseUpResult = tOptional(tObject({})); + scheme.PageMouseClickParams = tObject({ + x: tFloat, + y: tFloat, + delay: tOptional(tFloat), + button: tOptional(tEnum(["left", "right", "middle"])), + clickCount: tOptional(tInt) + }); + scheme.PageMouseClickResult = tOptional(tObject({})); + scheme.PageMouseWheelParams = tObject({ + deltaX: tFloat, + deltaY: tFloat + }); + scheme.PageMouseWheelResult = tOptional(tObject({})); + scheme.PageTouchscreenTapParams = tObject({ + x: tFloat, + y: tFloat + }); + scheme.PageTouchscreenTapResult = tOptional(tObject({})); + scheme.PageClearPageErrorsParams = tOptional(tObject({})); + scheme.PageClearPageErrorsResult = tOptional(tObject({})); + scheme.PagePageErrorsParams = tObject({ + filter: tOptional(tType("ConsoleMessagesFilter")) + }); + scheme.PagePageErrorsResult = tObject({ + errors: tArray(tType("SerializedError")) + }); + scheme.PagePdfParams = tObject({ + scale: tOptional(tFloat), + displayHeaderFooter: tOptional(tBoolean), + headerTemplate: tOptional(tString), + footerTemplate: tOptional(tString), + printBackground: tOptional(tBoolean), + landscape: tOptional(tBoolean), + pageRanges: tOptional(tString), + format: tOptional(tString), + width: tOptional(tString), + height: tOptional(tString), + preferCSSPageSize: tOptional(tBoolean), + margin: tOptional(tObject({ + top: tOptional(tString), + bottom: tOptional(tString), + left: tOptional(tString), + right: tOptional(tString) + })), + tagged: tOptional(tBoolean), + outline: tOptional(tBoolean) + }); + scheme.PagePdfResult = tObject({ + pdf: tBinary + }); + scheme.PageRequestsParams = tOptional(tObject({})); + scheme.PageRequestsResult = tObject({ + requests: tArray(tChannel(["Request"])) + }); + scheme.PageStartJSCoverageParams = tObject({ + resetOnNavigation: tOptional(tBoolean), + reportAnonymousScripts: tOptional(tBoolean) + }); + scheme.PageStartJSCoverageResult = tOptional(tObject({})); + scheme.PageStopJSCoverageParams = tOptional(tObject({})); + scheme.PageStopJSCoverageResult = tObject({ + entries: tArray(tObject({ + url: tString, + scriptId: tString, + source: tOptional(tString), + functions: tArray(tObject({ + functionName: tString, + isBlockCoverage: tBoolean, + ranges: tArray(tObject({ + startOffset: tInt, + endOffset: tInt, + count: tInt + })) + })) + })) + }); + scheme.PageStartCSSCoverageParams = tObject({ + resetOnNavigation: tOptional(tBoolean) + }); + scheme.PageStartCSSCoverageResult = tOptional(tObject({})); + scheme.PageStopCSSCoverageParams = tOptional(tObject({})); + scheme.PageStopCSSCoverageResult = tObject({ + entries: tArray(tObject({ + url: tString, + text: tOptional(tString), + ranges: tArray(tObject({ + start: tInt, + end: tInt + })) + })) + }); + scheme.PageBringToFrontParams = tOptional(tObject({})); + scheme.PageBringToFrontResult = tOptional(tObject({})); + scheme.PagePickLocatorParams = tOptional(tObject({})); + scheme.PagePickLocatorResult = tObject({ + selector: tString + }); + scheme.PageCancelPickLocatorParams = tOptional(tObject({})); + scheme.PageCancelPickLocatorResult = tOptional(tObject({})); + scheme.PageHideHighlightParams = tOptional(tObject({})); + scheme.PageHideHighlightResult = tOptional(tObject({})); + scheme.PageScreencastShowOverlayParams = tObject({ + html: tString, + duration: tOptional(tFloat) + }); + scheme.PageScreencastShowOverlayResult = tObject({ + id: tString + }); + scheme.PageScreencastRemoveOverlayParams = tObject({ + id: tString + }); + scheme.PageScreencastRemoveOverlayResult = tOptional(tObject({})); + scheme.PageScreencastChapterParams = tObject({ + title: tString, + description: tOptional(tString), + duration: tOptional(tFloat) + }); + scheme.PageScreencastChapterResult = tOptional(tObject({})); + scheme.PageScreencastSetOverlayVisibleParams = tObject({ + visible: tBoolean + }); + scheme.PageScreencastSetOverlayVisibleResult = tOptional(tObject({})); + scheme.PageScreencastShowActionsParams = tObject({ + duration: tOptional(tFloat), + position: tOptional(tEnum(["top-left", "top", "top-right", "bottom-left", "bottom", "bottom-right"])), + fontSize: tOptional(tInt), + cursor: tOptional(tEnum(["none", "pointer"])) + }); + scheme.PageScreencastShowActionsResult = tOptional(tObject({})); + scheme.PageScreencastHideActionsParams = tOptional(tObject({})); + scheme.PageScreencastHideActionsResult = tOptional(tObject({})); + scheme.PageScreencastStartParams = tObject({ + size: tOptional(tObject({ + width: tInt, + height: tInt + })), + quality: tOptional(tInt), + sendFrames: tOptional(tBoolean), + record: tOptional(tBoolean) + }); + scheme.PageScreencastStartResult = tObject({ + artifact: tOptional(tChannel(["Artifact"])) + }); + scheme.PageScreencastStopParams = tOptional(tObject({})); + scheme.PageScreencastStopResult = tOptional(tObject({})); + scheme.PageUpdateSubscriptionParams = tObject({ + event: tEnum(["console", "dialog", "fileChooser", "request", "response", "requestFinished", "requestFailed"]), + enabled: tBoolean + }); + scheme.PageUpdateSubscriptionResult = tOptional(tObject({})); + scheme.PageSetDockTileParams = tObject({ + image: tBinary + }); + scheme.PageSetDockTileResult = tOptional(tObject({})); + scheme.PageWebStorageItemsParams = tObject({ + kind: tEnum(["local", "session"]) + }); + scheme.PageWebStorageItemsResult = tObject({ + items: tArray(tType("NameValue")) + }); + scheme.PageWebStorageGetItemParams = tObject({ + kind: tEnum(["local", "session"]), + name: tString + }); + scheme.PageWebStorageGetItemResult = tObject({ + value: tOptional(tString) + }); + scheme.PageWebStorageSetItemParams = tObject({ + kind: tEnum(["local", "session"]), + name: tString, + value: tString + }); + scheme.PageWebStorageSetItemResult = tOptional(tObject({})); + scheme.PageWebStorageRemoveItemParams = tObject({ + kind: tEnum(["local", "session"]), + name: tString + }); + scheme.PageWebStorageRemoveItemResult = tOptional(tObject({})); + scheme.PageWebStorageClearParams = tObject({ + kind: tEnum(["local", "session"]) + }); + scheme.PageWebStorageClearResult = tOptional(tObject({})); + scheme.RootInitializer = tOptional(tObject({})); + scheme.RootInitializeParams = tObject({ + sdkLanguage: tType("SDKLanguage") + }); + scheme.RootInitializeResult = tObject({ + playwright: tChannel(["Playwright"]) + }); + scheme.PlaywrightInitializer = tObject({ + chromium: tChannel(["BrowserType"]), + firefox: tChannel(["BrowserType"]), + webkit: tChannel(["BrowserType"]), + android: tChannel(["Android"]), + electron: tChannel(["Electron"]), + utils: tOptional(tChannel(["LocalUtils"])), + preLaunchedBrowser: tOptional(tChannel(["Browser"])), + preConnectedAndroidDevice: tOptional(tChannel(["AndroidDevice"])), + socksSupport: tOptional(tChannel(["SocksSupport"])) + }); + scheme.PlaywrightNewRequestParams = tObject({ + baseURL: tOptional(tString), + userAgent: tOptional(tString), + ignoreHTTPSErrors: tOptional(tBoolean), + extraHTTPHeaders: tOptional(tArray(tType("NameValue"))), + failOnStatusCode: tOptional(tBoolean), + clientCertificates: tOptional(tArray(tObject({ + origin: tString, + cert: tOptional(tBinary), + key: tOptional(tBinary), + passphrase: tOptional(tString), + pfx: tOptional(tBinary) + }))), + maxRedirects: tOptional(tInt), + httpCredentials: tOptional(tObject({ + username: tString, + password: tString, + origin: tOptional(tString), + send: tOptional(tEnum(["always", "unauthorized"])) + })), + proxy: tOptional(tObject({ + server: tString, + bypass: tOptional(tString), + username: tOptional(tString), + password: tOptional(tString) + })), + storageState: tOptional(tObject({ + cookies: tOptional(tArray(tType("NetworkCookie"))), + origins: tOptional(tArray(tType("SetOriginStorage"))) + })), + tracesDir: tOptional(tString) + }); + scheme.PlaywrightNewRequestResult = tObject({ + request: tChannel(["APIRequestContext"]) + }); + scheme.DebugControllerInitializer = tOptional(tObject({})); + scheme.DebugControllerInspectRequestedEvent = tObject({ + selector: tString, + locator: tString, + ariaSnapshot: tString + }); + scheme.DebugControllerSetModeRequestedEvent = tObject({ + mode: tString + }); + scheme.DebugControllerStateChangedEvent = tObject({ + pageCount: tInt + }); + scheme.DebugControllerSourceChangedEvent = tObject({ + text: tString, + header: tOptional(tString), + footer: tOptional(tString), + actions: tOptional(tArray(tString)) + }); + scheme.DebugControllerPausedEvent = tObject({ + paused: tBoolean + }); + scheme.DebugControllerInitializeParams = tObject({ + codegenId: tString, + sdkLanguage: tType("SDKLanguage") + }); + scheme.DebugControllerInitializeResult = tOptional(tObject({})); + scheme.DebugControllerSetReportStateChangedParams = tObject({ + enabled: tBoolean + }); + scheme.DebugControllerSetReportStateChangedResult = tOptional(tObject({})); + scheme.DebugControllerSetRecorderModeParams = tObject({ + mode: tEnum(["inspecting", "recording", "none"]), + testIdAttributeName: tOptional(tString), + generateAutoExpect: tOptional(tBoolean) + }); + scheme.DebugControllerSetRecorderModeResult = tOptional(tObject({})); + scheme.DebugControllerHighlightParams = tObject({ + selector: tOptional(tString), + ariaTemplate: tOptional(tString) + }); + scheme.DebugControllerHighlightResult = tOptional(tObject({})); + scheme.DebugControllerHideHighlightParams = tOptional(tObject({})); + scheme.DebugControllerHideHighlightResult = tOptional(tObject({})); + scheme.DebugControllerResumeParams = tOptional(tObject({})); + scheme.DebugControllerResumeResult = tOptional(tObject({})); + scheme.DebugControllerKillParams = tOptional(tObject({})); + scheme.DebugControllerKillResult = tOptional(tObject({})); + scheme.SocksSupportInitializer = tOptional(tObject({})); + scheme.SocksSupportSocksRequestedEvent = tObject({ + uid: tString, + host: tString, + port: tInt + }); + scheme.SocksSupportSocksDataEvent = tObject({ + uid: tString, + data: tBinary + }); + scheme.SocksSupportSocksClosedEvent = tObject({ + uid: tString + }); + scheme.SocksSupportSocksConnectedParams = tObject({ + uid: tString, + host: tString, + port: tInt + }); + scheme.SocksSupportSocksConnectedResult = tOptional(tObject({})); + scheme.SocksSupportSocksFailedParams = tObject({ + uid: tString, + errorCode: tString + }); + scheme.SocksSupportSocksFailedResult = tOptional(tObject({})); + scheme.SocksSupportSocksDataParams = tObject({ + uid: tString, + data: tBinary + }); + scheme.SocksSupportSocksDataResult = tOptional(tObject({})); + scheme.SocksSupportSocksErrorParams = tObject({ + uid: tString, + error: tString + }); + scheme.SocksSupportSocksErrorResult = tOptional(tObject({})); + scheme.SocksSupportSocksEndParams = tObject({ + uid: tString + }); + scheme.SocksSupportSocksEndResult = tOptional(tObject({})); + scheme.JsonPipeInitializer = tOptional(tObject({})); + scheme.JsonPipeMessageEvent = tObject({ + message: tAny + }); + scheme.JsonPipeClosedEvent = tObject({ + reason: tOptional(tString) + }); + scheme.JsonPipeSendParams = tObject({ + message: tAny + }); + scheme.JsonPipeSendResult = tOptional(tObject({})); + scheme.JsonPipeCloseParams = tOptional(tObject({})); + scheme.JsonPipeCloseResult = tOptional(tObject({})); + scheme.ExpectedTextValue = tObject({ + string: tOptional(tString), + regexSource: tOptional(tString), + regexFlags: tOptional(tString), + matchSubstring: tOptional(tBoolean), + ignoreCase: tOptional(tBoolean), + normalizeWhiteSpace: tOptional(tBoolean) + }); + scheme.SelectorEngine = tObject({ + name: tString, + source: tString, + contentScript: tOptional(tBoolean) + }); + scheme.FormField = tObject({ + name: tString, + value: tOptional(tString), + file: tOptional(tObject({ + name: tString, + mimeType: tOptional(tString), + buffer: tBinary + })) + }); + scheme.LifecycleEvent = tEnum(["load", "domcontentloaded", "networkidle", "commit"]); + scheme.ConsoleMessagesFilter = tEnum(["all", "since-navigation"]); + scheme.RecorderSource = tObject({ + isRecorded: tBoolean, + id: tString, + label: tString, + text: tString, + language: tString, + highlight: tArray(tObject({ + line: tInt, + type: tString + })), + revealLine: tOptional(tInt), + group: tOptional(tString) + }); + scheme.IndexedDBDatabase = tObject({ + name: tString, + version: tInt, + stores: tArray(tObject({ + name: tString, + autoIncrement: tBoolean, + keyPath: tOptional(tString), + keyPathArray: tOptional(tArray(tString)), + records: tArray(tObject({ + key: tOptional(tAny), + keyEncoded: tOptional(tAny), + value: tOptional(tAny), + valueEncoded: tOptional(tAny) + })), + indexes: tArray(tObject({ + name: tString, + keyPath: tOptional(tString), + keyPathArray: tOptional(tArray(tString)), + multiEntry: tBoolean, + unique: tBoolean + })) + })) + }); + scheme.SetOriginStorage = tObject({ + origin: tString, + localStorage: tArray(tType("NameValue")), + indexedDB: tOptional(tArray(tType("IndexedDBDatabase"))) + }); + scheme.OriginStorage = tObject({ + origin: tString, + localStorage: tArray(tType("NameValue")), + indexedDB: tOptional(tArray(tType("IndexedDBDatabase"))) + }); + scheme.RecordHarOptions = tObject({ + content: tOptional(tEnum(["embed", "attach", "omit"])), + mode: tOptional(tEnum(["full", "minimal"])), + urlGlob: tOptional(tString), + urlRegexSource: tOptional(tString), + urlRegexFlags: tOptional(tString), + harPath: tOptional(tString), + resourcesDir: tOptional(tString) + }); + scheme.CDPSessionInitializer = tOptional(tObject({})); + scheme.CDPSessionEventEvent = tObject({ + method: tString, + params: tOptional(tAny) + }); + scheme.CDPSessionCloseEvent = tOptional(tObject({})); + scheme.CDPSessionSendParams = tObject({ + method: tString, + params: tOptional(tAny) + }); + scheme.CDPSessionSendResult = tObject({ + result: tAny + }); + scheme.CDPSessionDetachParams = tOptional(tObject({})); + scheme.CDPSessionDetachResult = tOptional(tObject({})); + scheme.BindingCallInitializer = tObject({ + frame: tChannel(["Frame"]), + name: tString, + args: tArray(tType("SerializedValue")) + }); + scheme.BindingCallRejectParams = tObject({ + error: tType("SerializedError") + }); + scheme.BindingCallRejectResult = tOptional(tObject({})); + scheme.BindingCallResolveParams = tObject({ + result: tType("SerializedArgument") + }); + scheme.BindingCallResolveResult = tOptional(tObject({})); + scheme.DebuggerInitializer = tOptional(tObject({})); + scheme.DebuggerPausedStateChangedEvent = tObject({ + pausedDetails: tOptional(tObject({ + location: tObject({ + file: tString, + line: tOptional(tInt), + column: tOptional(tInt) + }), + title: tString, + stack: tOptional(tString) + })) + }); + scheme.DebuggerRequestPauseParams = tOptional(tObject({})); + scheme.DebuggerRequestPauseResult = tOptional(tObject({})); + scheme.DebuggerResumeParams = tOptional(tObject({})); + scheme.DebuggerResumeResult = tOptional(tObject({})); + scheme.DebuggerNextParams = tOptional(tObject({})); + scheme.DebuggerNextResult = tOptional(tObject({})); + scheme.DebuggerRunToParams = tObject({ + location: tObject({ + file: tString, + line: tOptional(tInt), + column: tOptional(tInt) + }) + }); + scheme.DebuggerRunToResult = tOptional(tObject({})); + scheme.DialogInitializer = tObject({ + page: tOptional(tChannel(["Page"])), + type: tString, + message: tString, + defaultValue: tString + }); + scheme.DialogAcceptParams = tObject({ + promptText: tOptional(tString) + }); + scheme.DialogAcceptResult = tOptional(tObject({})); + scheme.DialogDismissParams = tOptional(tObject({})); + scheme.DialogDismissResult = tOptional(tObject({})); + scheme.SerializedValue = tObject({ + n: tOptional(tFloat), + b: tOptional(tBoolean), + s: tOptional(tString), + v: tOptional(tEnum(["null", "undefined", "NaN", "Infinity", "-Infinity", "-0"])), + d: tOptional(tString), + u: tOptional(tString), + bi: tOptional(tString), + ta: tOptional(tObject({ + b: tBinary, + k: tEnum(["i8", "ui8", "ui8c", "i16", "ui16", "i32", "ui32", "f32", "f64", "bi64", "bui64"]) + })), + e: tOptional(tObject({ + m: tString, + n: tString, + s: tString + })), + r: tOptional(tObject({ + p: tString, + f: tString + })), + a: tOptional(tArray(tType("SerializedValue"))), + o: tOptional(tArray(tObject({ + k: tString, + v: tType("SerializedValue") + }))), + h: tOptional(tInt), + id: tOptional(tInt), + ref: tOptional(tInt) + }); + scheme.SerializedArgument = tObject({ + value: tType("SerializedValue"), + handles: tArray(tChannel("*")) + }); + scheme.SerializedError = tObject({ + error: tOptional(tObject({ + message: tString, + name: tString, + stack: tOptional(tString) + })), + value: tOptional(tType("SerializedValue")) + }); + scheme.StackFrame = tObject({ + file: tString, + line: tInt, + column: tInt, + function: tOptional(tString) + }); + scheme.VirtualCredential = tObject({ + id: tString, + rpId: tString, + userHandle: tString, + privateKey: tString, + publicKey: tString + }); + scheme.Point = tObject({ + x: tFloat, + y: tFloat + }); + scheme.Rect = tObject({ + x: tFloat, + y: tFloat, + width: tFloat, + height: tFloat + }); + scheme.URLPattern = tObject({ + hash: tString, + hostname: tString, + password: tString, + pathname: tString, + port: tString, + protocol: tString, + search: tString, + username: tString + }); + scheme.NameValue = tObject({ + name: tString, + value: tString + }); + scheme.TracingInitializer = tOptional(tObject({})); + scheme.TracingTracingStartParams = tObject({ + name: tOptional(tString), + snapshots: tOptional(tBoolean), + screenshots: tOptional(tBoolean), + live: tOptional(tBoolean) + }); + scheme.TracingTracingStartResult = tOptional(tObject({})); + scheme.TracingTracingStartChunkParams = tObject({ + name: tOptional(tString), + title: tOptional(tString) + }); + scheme.TracingTracingStartChunkResult = tObject({ + traceName: tString + }); + scheme.TracingTracingGroupParams = tObject({ + name: tString, + location: tOptional(tObject({ + file: tString, + line: tOptional(tInt), + column: tOptional(tInt) + })) + }); + scheme.TracingTracingGroupResult = tOptional(tObject({})); + scheme.TracingTracingGroupEndParams = tOptional(tObject({})); + scheme.TracingTracingGroupEndResult = tOptional(tObject({})); + scheme.TracingTracingStopChunkParams = tObject({ + mode: tEnum(["archive", "discard", "entries"]) + }); + scheme.TracingTracingStopChunkResult = tObject({ + artifact: tOptional(tChannel(["Artifact"])), + entries: tOptional(tArray(tType("NameValue"))) + }); + scheme.TracingTracingStopParams = tOptional(tObject({})); + scheme.TracingTracingStopResult = tOptional(tObject({})); + scheme.TracingHarStartParams = tObject({ + page: tOptional(tChannel(["Page"])), + options: tType("RecordHarOptions") + }); + scheme.TracingHarStartResult = tObject({ + harId: tString + }); + scheme.TracingHarExportParams = tObject({ + harId: tOptional(tString), + mode: tEnum(["archive", "entries"]) + }); + scheme.TracingHarExportResult = tObject({ + artifact: tOptional(tChannel(["Artifact"])), + entries: tOptional(tArray(tType("NameValue"))) + }); + scheme.WorkerInitializer = tObject({ + url: tString + }); + scheme.WorkerConsoleEvent = tObject({ + type: tString, + text: tString, + args: tArray(tChannel(["ElementHandle", "JSHandle"])), + location: tObject({ + url: tString, + lineNumber: tInt, + columnNumber: tInt + }), + timestamp: tFloat + }); + scheme.WorkerCloseEvent = tOptional(tObject({})); + scheme.WorkerDisconnectParams = tObject({ + reason: tOptional(tString) + }); + scheme.WorkerDisconnectResult = tOptional(tObject({})); + scheme.WorkerEvaluateExpressionParams = tObject({ + expression: tString, + isFunction: tOptional(tBoolean), + arg: tType("SerializedArgument") + }); + scheme.WorkerEvaluateExpressionResult = tObject({ + value: tType("SerializedValue") + }); + scheme.WorkerEvaluateExpressionHandleParams = tObject({ + expression: tString, + isFunction: tOptional(tBoolean), + arg: tType("SerializedArgument") + }); + scheme.WorkerEvaluateExpressionHandleResult = tObject({ + handle: tChannel(["ElementHandle", "JSHandle"]) + }); + scheme.WorkerUpdateSubscriptionParams = tObject({ + event: tEnum(["console"]), + enabled: tBoolean + }); + scheme.WorkerUpdateSubscriptionResult = tOptional(tObject({})); + } +}); + +// packages/playwright-core/src/server/protocolError.ts +function isProtocolError(e) { + return e instanceof ProtocolError; +} +function isSessionClosedError(e) { + return e instanceof ProtocolError && (e.type === "closed" || e.type === "crashed"); +} +var ProtocolError; +var init_protocolError = __esm({ + "packages/playwright-core/src/server/protocolError.ts"() { + "use strict"; + init_stackTrace(); + ProtocolError = class extends Error { + constructor(type3, method, logs) { + super(); + this.type = type3; + this.method = method; + this.logs = logs; + } + setMessage(message) { + rewriteErrorMessage(this, `Protocol error (${this.method}): ${message}`); + } + browserLogMessage() { + return this.logs ? "\nBrowser logs:\n" + this.logs : ""; + } + }; + } +}); + +// packages/playwright-core/src/server/callLog.ts +function compressCallLog(log2) { + const lines = []; + for (const block of findRepeatedSubsequences(log2)) { + for (let i = 0; i < block.sequence.length; i++) { + const line = block.sequence[i]; + const leadingWhitespace = line.match(/^\s*/); + const whitespacePrefix = " " + leadingWhitespace?.[0] || ""; + const countPrefix = `${block.count} \xD7 `; + if (block.count > 1 && i === 0) + lines.push(whitespacePrefix + countPrefix + line.trim()); + else if (block.count > 1) + lines.push(whitespacePrefix + " ".repeat(countPrefix.length - 2) + "- " + line.trim()); + else + lines.push(whitespacePrefix + "- " + line.trim()); + } + } + return lines; +} +function findRepeatedSubsequences(s) { + const n = s.length; + const result2 = []; + let i = 0; + const arraysEqual = (a1, a2) => { + if (a1.length !== a2.length) + return false; + for (let j = 0; j < a1.length; j++) { + if (a1[j] !== a2[j]) + return false; + } + return true; + }; + while (i < n) { + let maxRepeatCount = 1; + let maxRepeatSubstr = [s[i]]; + let maxRepeatLength = 1; + for (let p = 1; p <= n - i; p++) { + const substr = s.slice(i, i + p); + let k = 1; + while (i + p * k <= n && arraysEqual(s.slice(i + p * (k - 1), i + p * k), substr)) + k += 1; + k -= 1; + if (k > 1 && k * p > maxRepeatCount * maxRepeatLength) { + maxRepeatCount = k; + maxRepeatSubstr = substr; + maxRepeatLength = p; + } + } + result2.push({ sequence: maxRepeatSubstr, count: maxRepeatCount }); + i += maxRepeatLength * maxRepeatCount; + } + return result2; +} +var findRepeatedSubsequencesForTest; +var init_callLog = __esm({ + "packages/playwright-core/src/server/callLog.ts"() { + "use strict"; + findRepeatedSubsequencesForTest = findRepeatedSubsequences; + } +}); + +// packages/playwright-core/src/server/dispatchers/dispatcher.ts +function setMaxDispatchersForTest(value2) { + maxDispatchersOverride = value2; +} +function maxDispatchersForBucket(gcBucket) { + return maxDispatchersOverride ?? { + "JSHandle": 1e5, + "ElementHandle": 1e5 + }[gcBucket] ?? 1e4; +} +var import_events5, metadataValidator, waitInfoValidator, maxDispatchersOverride, Dispatcher, RootDispatcher, DispatcherConnection; +var init_dispatcher = __esm({ + "packages/playwright-core/src/server/dispatchers/dispatcher.ts"() { + "use strict"; + import_events5 = require("events"); + init_protocolMetainfo(); + init_eventsHelper(); + init_debug(); + init_assert(); + init_time(); + init_stackTrace(); + init_validator(); + init_errors(); + init_instrumentation(); + init_protocolError(); + init_callLog(); + init_progress(); + metadataValidator = createMetadataValidator(); + waitInfoValidator = createWaitInfoValidator(); + Dispatcher = class extends import_events5.EventEmitter { + constructor(parent, object, type3, initializer, gcBucket) { + super(); + this._dispatchers = /* @__PURE__ */ new Map(); + this._disposed = false; + this._eventListeners = []; + this._activeProgressControllers = /* @__PURE__ */ new Set(); + this.connection = parent instanceof DispatcherConnection ? parent : parent.connection; + this._parent = parent instanceof DispatcherConnection ? void 0 : parent; + const guid = object.guid; + this._guid = guid; + this._type = type3; + this._object = object; + this._gcBucket = gcBucket ?? type3; + this.connection.registerDispatcher(this); + if (this._parent) { + assert(!this._parent._dispatchers.has(guid)); + this._parent._dispatchers.set(guid, this); + } + if (this._parent) + this.connection.sendCreate(this._parent, type3, guid, initializer); + this.connection.maybeDisposeStaleDispatchers(this._gcBucket); + } + parentScope() { + return this._parent; + } + addObjectListener(eventName, handler) { + this._eventListeners.push(eventsHelper.addEventListener(this._object, eventName, handler)); + } + adopt(child) { + if (child._parent === this) + return; + const oldParent = child._parent; + oldParent._dispatchers.delete(child._guid); + this._dispatchers.set(child._guid, child); + child._parent = this; + this.connection.sendAdopt(this, child); + } + async _runCommand(callMetadata, method, validParams) { + const controller = ProgressController.createForSdkObject(this._object, callMetadata); + this._activeProgressControllers.add(controller); + try { + return await controller.run((progress2) => this[method](validParams, progress2), validParams?.timeout); + } finally { + this._activeProgressControllers.delete(controller); + } + } + _dispatchEvent(method, params2) { + if (this._disposed) { + if (isUnderTest()) + throw new Error(`${this._guid} is sending "${String(method)}" event after being disposed`); + return; + } + this.connection.sendEvent(this, method, params2); + } + _dispose(reason) { + this._disposeRecursively(new TargetClosedError(this._object.closeReason())); + this.connection.sendDispose(this, reason); + } + _onDispose() { + } + async stopPendingOperations(error) { + const controllers = []; + const collect = (dispatcher) => { + controllers.push(...dispatcher._activeProgressControllers); + for (const child of [...dispatcher._dispatchers.values()]) + collect(child); + }; + collect(this); + await Promise.all(controllers.map((controller) => controller.abort(error))); + } + _disposeRecursively(error) { + assert(!this._disposed, `${this._guid} is disposed more than once`); + this._onDispose(); + this._disposed = true; + eventsHelper.removeEventListeners(this._eventListeners); + this._parent?._dispatchers.delete(this._guid); + const list = this.connection._dispatchersByBucket.get(this._gcBucket); + list?.delete(this._guid); + this.connection._dispatcherByGuid.delete(this._guid); + this.connection._dispatcherByObject.delete(this._object); + for (const dispatcher of [...this._dispatchers.values()]) + dispatcher._disposeRecursively(error); + this._dispatchers.clear(); + } + _debugScopeState() { + return { + _guid: this._guid, + objects: Array.from(this._dispatchers.values()).map((o) => o._debugScopeState()) + }; + } + }; + RootDispatcher = class extends Dispatcher { + constructor(connection, createPlaywright2) { + super(connection, createRootSdkObject(), "Root", {}); + this.createPlaywright = createPlaywright2; + this._initialized = false; + } + async initialize(params2, progress2) { + assert(this.createPlaywright); + assert(!this._initialized); + this._initialized = true; + return { + playwright: await progress2.race(this.createPlaywright(this, params2)) + }; + } + }; + DispatcherConnection = class { + constructor(isInProcess) { + this._dispatcherByGuid = /* @__PURE__ */ new Map(); + this._dispatcherByObject = /* @__PURE__ */ new Map(); + this._dispatchersByBucket = /* @__PURE__ */ new Map(); + this.onmessage = (message) => { + }; + this._waitOperations = /* @__PURE__ */ new Map(); + this._isInProcess = !!isInProcess; + } + sendEvent(dispatcher, event, params2) { + const validator = findValidator(dispatcher._type, event, "Event"); + params2 = validator(params2, "", this._validatorToWireContext()); + this.onmessage({ guid: dispatcher._guid, method: event, params: params2 }); + } + sendCreate(parent, type3, guid, initializer) { + const validator = findValidator(type3, "", "Initializer"); + initializer = validator(initializer, "", this._validatorToWireContext()); + this.onmessage({ guid: parent._guid, method: "__create__", params: { type: type3, initializer, guid } }); + } + sendAdopt(parent, dispatcher) { + this.onmessage({ guid: parent._guid, method: "__adopt__", params: { guid: dispatcher._guid } }); + } + sendDispose(dispatcher, reason) { + this.onmessage({ guid: dispatcher._guid, method: "__dispose__", params: { reason } }); + } + _validatorToWireContext() { + return { + tChannelImpl: this._tChannelImplToWire.bind(this), + binary: this._isInProcess ? "buffer" : "toBase64", + isUnderTest + }; + } + _validatorFromWireContext() { + return { + tChannelImpl: this._tChannelImplFromWire.bind(this), + binary: this._isInProcess ? "buffer" : "fromBase64", + isUnderTest + }; + } + _tChannelImplFromWire(names, arg, path59, context2) { + if (arg && typeof arg === "object" && typeof arg.guid === "string") { + const guid = arg.guid; + const dispatcher = this._dispatcherByGuid.get(guid); + if (!dispatcher) + throw new ValidationError(`${path59}: no object with guid ${guid}`); + if (names !== "*" && !names.includes(dispatcher._type)) + throw new ValidationError(`${path59}: object with guid ${guid} has type ${dispatcher._type}, expected ${names.toString()}`); + return dispatcher; + } + throw new ValidationError(`${path59}: expected guid for ${names.toString()}`); + } + _tChannelImplToWire(names, arg, path59, context2) { + if (arg instanceof Dispatcher) { + if (names !== "*" && !names.includes(arg._type)) + throw new ValidationError(`${path59}: dispatcher with guid ${arg._guid} has type ${arg._type}, expected ${names.toString()}`); + return { guid: arg._guid }; + } + throw new ValidationError(`${path59}: expected dispatcher ${names.toString()}`); + } + existingDispatcher(object) { + return this._dispatcherByObject.get(object); + } + registerDispatcher(dispatcher) { + assert(!this._dispatcherByGuid.has(dispatcher._guid)); + this._dispatcherByGuid.set(dispatcher._guid, dispatcher); + this._dispatcherByObject.set(dispatcher._object, dispatcher); + let list = this._dispatchersByBucket.get(dispatcher._gcBucket); + if (!list) { + list = /* @__PURE__ */ new Set(); + this._dispatchersByBucket.set(dispatcher._gcBucket, list); + } + list.add(dispatcher._guid); + } + maybeDisposeStaleDispatchers(gcBucket) { + const maxDispatchers = maxDispatchersForBucket(gcBucket); + const list = this._dispatchersByBucket.get(gcBucket); + if (!list || list.size <= maxDispatchers) + return; + const dispatchersArray = [...list]; + const disposeCount = maxDispatchers / 10 | 0; + this._dispatchersByBucket.set(gcBucket, new Set(dispatchersArray.slice(disposeCount))); + for (let i = 0; i < disposeCount; ++i) { + const d = this._dispatcherByGuid.get(dispatchersArray[i]); + if (!d) + continue; + d._dispose("gc"); + } + } + async dispatch(message) { + const { id, guid, method, params: params2, metadata } = message; + const dispatcher = this._dispatcherByGuid.get(guid); + if (method === "__waitInfo__") { + if (dispatcher) + await this._dispatchWaitInfo(id, dispatcher, params2, metadata); + return; + } + if (!dispatcher) { + this.onmessage({ id, error: serializeError(new TargetClosedError(void 0)) }); + return; + } + let validParams; + let validMetadata; + try { + const validator = findValidator(dispatcher._type, method, "Params"); + const validatorContext = this._validatorFromWireContext(); + validParams = validator(params2, "", validatorContext); + validMetadata = metadataValidator(metadata, "", validatorContext); + if (typeof dispatcher[method] !== "function") + throw new Error(`Mismatching dispatcher: "${dispatcher._type}" does not implement "${method}"`); + } catch (e) { + this.onmessage({ id, error: serializeError(e) }); + return; + } + const metainfo = getMetainfo({ type: dispatcher._type, method }); + if (metainfo?.internal) { + validMetadata.internal = true; + } + const sdkObject = dispatcher._object; + const callMetadata = { + id: `call@${id}`, + location: validMetadata.location, + title: validMetadata.title, + internal: validMetadata.internal, + stepId: validMetadata.stepId, + objectId: sdkObject.guid, + pageId: sdkObject.attribution?.page?.guid, + frameId: sdkObject.attribution?.frame?.guid, + startTime: monotonicTime(), + endTime: 0, + type: dispatcher._type, + method, + params: params2 || {}, + log: [] + }; + await sdkObject.instrumentation.onBeforeCall(sdkObject, callMetadata); + const response2 = { id }; + try { + if (this._dispatcherByGuid.get(guid) !== dispatcher) + throw new TargetClosedError(sdkObject.closeReason()); + const result2 = await dispatcher._runCommand(callMetadata, method, validParams); + const validator = findValidator(dispatcher._type, method, "Result"); + response2.result = validator(result2, "", this._validatorToWireContext()); + callMetadata.result = result2; + } catch (e) { + if (isTargetClosedError(e)) { + const reason = sdkObject.closeReason(); + if (reason) + rewriteErrorMessage(e, reason); + } else if (isProtocolError(e)) { + if (e.type === "closed") + e = new TargetClosedError(sdkObject.closeReason(), e.browserLogMessage()); + else if (e.type === "crashed") + rewriteErrorMessage(e, "Target crashed " + e.browserLogMessage()); + } + response2.error = serializeError(e); + const detailsValidator = maybeFindValidator(dispatcher._type, method, "ErrorDetails"); + if (detailsValidator) + response2.errorDetails = detailsValidator(e?.details ?? {}, "", this._validatorToWireContext()); + callMetadata.error = response2.error; + } finally { + callMetadata.endTime = monotonicTime(); + await sdkObject.instrumentation.onAfterCall(sdkObject, callMetadata); + if (metainfo?.slowMo) + await this._doSlowMo(sdkObject); + } + if (response2.error) + response2.log = compressCallLog(callMetadata.log); + this.onmessage(response2); + } + async _doSlowMo(sdkObject) { + const slowMo = sdkObject.attribution.browser?.options.slowMo; + if (slowMo) + await new Promise((f) => setTimeout(f, slowMo)); + } + async _dispatchWaitInfo(id, dispatcher, params2, metadata) { + let info; + let validMetadata; + try { + const validatorContext = this._validatorFromWireContext(); + info = waitInfoValidator(params2, "", validatorContext); + validMetadata = metadataValidator(metadata, "", validatorContext); + } catch { + return; + } + const sdkObject = dispatcher._object; + if (info.phase === "before") { + const callMetadata = { + id: `call@${id}`, + location: validMetadata.location, + title: validMetadata.title, + internal: validMetadata.internal, + stepId: validMetadata.stepId, + objectId: sdkObject.guid, + pageId: sdkObject.attribution?.page?.guid, + frameId: sdkObject.attribution?.frame?.guid, + startTime: monotonicTime(), + endTime: 0, + type: dispatcher._type, + method: "__waitInfo__", + params: params2 || {}, + log: [] + }; + this._waitOperations.set(info.waitId, callMetadata); + await sdkObject.instrumentation.onBeforeCall(sdkObject, callMetadata).catch(() => { + }); + return; + } + const originalMetadata = this._waitOperations.get(info.waitId); + if (!originalMetadata) + return; + if (info.phase === "log" && info.message) { + originalMetadata.log.push(info.message); + sdkObject.instrumentation.onCallLog(sdkObject, originalMetadata, "api", info.message); + return; + } + if (info.phase === "after") { + originalMetadata.endTime = monotonicTime(); + originalMetadata.error = info.error ? { error: { name: "Error", message: info.error } } : void 0; + this._waitOperations.delete(info.waitId); + await sdkObject.instrumentation.onAfterCall(sdkObject, originalMetadata).catch(() => { + }); + } + } + }; + } +}); + +// packages/isomorphic/utilityScriptSerializers.ts +function isRegExp5(obj) { + try { + return obj instanceof RegExp || Object.prototype.toString.call(obj) === "[object RegExp]"; + } catch (error) { + return false; + } +} +function isDate2(obj) { + try { + return obj instanceof Date || Object.prototype.toString.call(obj) === "[object Date]"; + } catch (error) { + return false; + } +} +function isURL2(obj) { + try { + return obj instanceof URL || Object.prototype.toString.call(obj) === "[object URL]"; + } catch (error) { + return false; + } +} +function isError3(obj) { + try { + return obj instanceof Error || obj && Object.getPrototypeOf(obj)?.name === "Error"; + } catch (error) { + return false; + } +} +function isTypedArray(obj, constructor) { + try { + return obj instanceof constructor || Object.prototype.toString.call(obj) === `[object ${constructor.name}]`; + } catch (error) { + return false; + } +} +function isArrayBuffer(obj) { + try { + return obj instanceof ArrayBuffer || Object.prototype.toString.call(obj) === "[object ArrayBuffer]"; + } catch (error) { + return false; + } +} +function typedArrayToBase64(array) { + if ("toBase64" in array) + return array.toBase64(); + const binary = Array.from(new Uint8Array(array.buffer, array.byteOffset, array.byteLength)).map((b) => String.fromCharCode(b)).join(""); + return btoa(binary); +} +function base64ToTypedArray(base64, TypedArrayConstructor) { + const binary = atob(base64); + const bytes = new Uint8Array(binary.length); + for (let i = 0; i < binary.length; i++) + bytes[i] = binary.charCodeAt(i); + return new TypedArrayConstructor(bytes.buffer); +} +function parseEvaluationResultValue(value2, handles = [], refs = /* @__PURE__ */ new Map()) { + if (Object.is(value2, void 0)) + return void 0; + if (typeof value2 === "object" && value2) { + if ("ref" in value2) + return refs.get(value2.ref); + if ("v" in value2) { + if (value2.v === "undefined") + return void 0; + if (value2.v === "null") + return null; + if (value2.v === "NaN") + return NaN; + if (value2.v === "Infinity") + return Infinity; + if (value2.v === "-Infinity") + return -Infinity; + if (value2.v === "-0") + return -0; + return void 0; + } + if ("d" in value2) { + return new Date(value2.d); + } + if ("u" in value2) + return new URL(value2.u); + if ("bi" in value2) + return BigInt(value2.bi); + if ("e" in value2) { + const error = new Error(value2.e.m); + error.name = value2.e.n; + error.stack = value2.e.s; + return error; + } + if ("r" in value2) + return new RegExp(value2.r.p, value2.r.f); + if ("a" in value2) { + const result2 = []; + refs.set(value2.id, result2); + for (const a of value2.a) + result2.push(parseEvaluationResultValue(a, handles, refs)); + return result2; + } + if ("o" in value2) { + const result2 = {}; + refs.set(value2.id, result2); + for (const { k, v } of value2.o) { + if (k === "__proto__") + continue; + result2[k] = parseEvaluationResultValue(v, handles, refs); + } + return result2; + } + if ("h" in value2) + return handles[value2.h]; + if ("ta" in value2) + return base64ToTypedArray(value2.ta.b, typedArrayConstructors[value2.ta.k]); + if ("ab" in value2) + return base64ToTypedArray(value2.ab.b, Uint8Array).buffer; + } + return value2; +} +function serializeAsCallArgument(value2, handleSerializer) { + return serialize(value2, handleSerializer, { visited: /* @__PURE__ */ new Map(), lastId: 0 }); +} +function serialize(value2, handleSerializer, visitorInfo) { + if (value2 && typeof value2 === "object") { + if (typeof globalThis.Window === "function" && value2 instanceof globalThis.Window) + return "ref: "; + if (typeof globalThis.Document === "function" && value2 instanceof globalThis.Document) + return "ref: "; + if (typeof globalThis.Node === "function" && value2 instanceof globalThis.Node) + return "ref: "; + } + return innerSerialize(value2, handleSerializer, visitorInfo); +} +function innerSerialize(value2, handleSerializer, visitorInfo) { + const result2 = handleSerializer(value2); + if ("fallThrough" in result2) + value2 = result2.fallThrough; + else + return result2; + if (typeof value2 === "symbol") + return { v: "undefined" }; + if (Object.is(value2, void 0)) + return { v: "undefined" }; + if (Object.is(value2, null)) + return { v: "null" }; + if (Object.is(value2, NaN)) + return { v: "NaN" }; + if (Object.is(value2, Infinity)) + return { v: "Infinity" }; + if (Object.is(value2, -Infinity)) + return { v: "-Infinity" }; + if (Object.is(value2, -0)) + return { v: "-0" }; + if (typeof value2 === "boolean") + return value2; + if (typeof value2 === "number") + return value2; + if (typeof value2 === "string") + return value2; + if (typeof value2 === "bigint") + return { bi: value2.toString() }; + if (isError3(value2)) { + let stack; + if (value2.stack?.startsWith(value2.name + ": " + value2.message)) { + stack = value2.stack; + } else { + stack = `${value2.name}: ${value2.message} +${value2.stack}`; + } + return { e: { n: value2.name, m: value2.message, s: stack } }; + } + if (isDate2(value2)) + return { d: value2.toJSON() }; + if (isURL2(value2)) + return { u: value2.toJSON() }; + if (isRegExp5(value2)) + return { r: { p: value2.source, f: value2.flags } }; + for (const [k, ctor] of Object.entries(typedArrayConstructors)) { + if (isTypedArray(value2, ctor)) + return { ta: { b: typedArrayToBase64(value2), k } }; + } + if (isArrayBuffer(value2)) + return { ab: { b: typedArrayToBase64(new Uint8Array(value2)) } }; + const id = visitorInfo.visited.get(value2); + if (id) + return { ref: id }; + if (Array.isArray(value2)) { + const a = []; + const id2 = ++visitorInfo.lastId; + visitorInfo.visited.set(value2, id2); + for (let i = 0; i < value2.length; ++i) + a.push(serialize(value2[i], handleSerializer, visitorInfo)); + return { a, id: id2 }; + } + if (typeof value2 === "object") { + const o = []; + const id2 = ++visitorInfo.lastId; + visitorInfo.visited.set(value2, id2); + for (const name of Object.keys(value2)) { + let item; + try { + item = value2[name]; + } catch (e) { + continue; + } + if (name === "toJSON" && typeof item === "function") + o.push({ k: name, v: { o: [], id: 0 } }); + else + o.push({ k: name, v: serialize(item, handleSerializer, visitorInfo) }); + } + let jsonWrapper; + try { + if (o.length === 0 && value2.toJSON && typeof value2.toJSON === "function") + jsonWrapper = { value: value2.toJSON() }; + } catch (e) { + } + if (jsonWrapper) + return innerSerialize(jsonWrapper.value, handleSerializer, visitorInfo); + return { o, id: id2 }; + } +} +var typedArrayConstructors; +var init_utilityScriptSerializers = __esm({ + "packages/isomorphic/utilityScriptSerializers.ts"() { + "use strict"; + typedArrayConstructors = { + i8: Int8Array, + ui8: Uint8Array, + ui8c: Uint8ClampedArray, + i16: Int16Array, + ui16: Uint16Array, + i32: Int32Array, + ui32: Uint32Array, + // TODO: add Float16Array once it's in baseline + f32: Float32Array, + f64: Float64Array, + bi64: BigInt64Array, + bui64: BigUint64Array + }; + } +}); + +// packages/playwright-core/src/generated/utilityScriptSource.ts +var source3; +var init_utilityScriptSource = __esm({ + "packages/playwright-core/src/generated/utilityScriptSource.ts"() { + "use strict"; + source3 = '\nvar __commonJS = obj => {\n let required = false;\n let result;\n return function __require() {\n if (!required) {\n required = true;\n let fn;\n for (const name in obj) { fn = obj[name]; break; }\n const module = { exports: {} };\n fn(module.exports, module);\n result = module.exports;\n }\n return result;\n }\n};\nvar __export = (target, all) => {for (var name in all) target[name] = all[name];};\nvar __toESM = mod => ({ ...mod, \'default\': mod });\nvar __toCommonJS = mod => ({ ...mod, __esModule: true });\n\n\n// packages/injected/src/utilityScript.ts\nvar utilityScript_exports = {};\n__export(utilityScript_exports, {\n UtilityScript: () => UtilityScript\n});\nmodule.exports = __toCommonJS(utilityScript_exports);\n\n// packages/isomorphic/utilityScriptSerializers.ts\nfunction isRegExp(obj) {\n try {\n return obj instanceof RegExp || Object.prototype.toString.call(obj) === "[object RegExp]";\n } catch (error) {\n return false;\n }\n}\nfunction isDate(obj) {\n try {\n return obj instanceof Date || Object.prototype.toString.call(obj) === "[object Date]";\n } catch (error) {\n return false;\n }\n}\nfunction isURL(obj) {\n try {\n return obj instanceof URL || Object.prototype.toString.call(obj) === "[object URL]";\n } catch (error) {\n return false;\n }\n}\nfunction isError(obj) {\n var _a;\n try {\n return obj instanceof Error || obj && ((_a = Object.getPrototypeOf(obj)) == null ? void 0 : _a.name) === "Error";\n } catch (error) {\n return false;\n }\n}\nfunction isTypedArray(obj, constructor) {\n try {\n return obj instanceof constructor || Object.prototype.toString.call(obj) === `[object ${constructor.name}]`;\n } catch (error) {\n return false;\n }\n}\nfunction isArrayBuffer(obj) {\n try {\n return obj instanceof ArrayBuffer || Object.prototype.toString.call(obj) === "[object ArrayBuffer]";\n } catch (error) {\n return false;\n }\n}\nvar typedArrayConstructors = {\n i8: Int8Array,\n ui8: Uint8Array,\n ui8c: Uint8ClampedArray,\n i16: Int16Array,\n ui16: Uint16Array,\n i32: Int32Array,\n ui32: Uint32Array,\n // TODO: add Float16Array once it\'s in baseline\n f32: Float32Array,\n f64: Float64Array,\n bi64: BigInt64Array,\n bui64: BigUint64Array\n};\nfunction typedArrayToBase64(array) {\n if ("toBase64" in array)\n return array.toBase64();\n const binary = Array.from(new Uint8Array(array.buffer, array.byteOffset, array.byteLength)).map((b) => String.fromCharCode(b)).join("");\n return btoa(binary);\n}\nfunction base64ToTypedArray(base64, TypedArrayConstructor) {\n const binary = atob(base64);\n const bytes = new Uint8Array(binary.length);\n for (let i = 0; i < binary.length; i++)\n bytes[i] = binary.charCodeAt(i);\n return new TypedArrayConstructor(bytes.buffer);\n}\nfunction parseEvaluationResultValue(value, handles = [], refs = /* @__PURE__ */ new Map()) {\n if (Object.is(value, void 0))\n return void 0;\n if (typeof value === "object" && value) {\n if ("ref" in value)\n return refs.get(value.ref);\n if ("v" in value) {\n if (value.v === "undefined")\n return void 0;\n if (value.v === "null")\n return null;\n if (value.v === "NaN")\n return NaN;\n if (value.v === "Infinity")\n return Infinity;\n if (value.v === "-Infinity")\n return -Infinity;\n if (value.v === "-0")\n return -0;\n return void 0;\n }\n if ("d" in value) {\n return new Date(value.d);\n }\n if ("u" in value)\n return new URL(value.u);\n if ("bi" in value)\n return BigInt(value.bi);\n if ("e" in value) {\n const error = new Error(value.e.m);\n error.name = value.e.n;\n error.stack = value.e.s;\n return error;\n }\n if ("r" in value)\n return new RegExp(value.r.p, value.r.f);\n if ("a" in value) {\n const result = [];\n refs.set(value.id, result);\n for (const a of value.a)\n result.push(parseEvaluationResultValue(a, handles, refs));\n return result;\n }\n if ("o" in value) {\n const result = {};\n refs.set(value.id, result);\n for (const { k, v } of value.o) {\n if (k === "__proto__")\n continue;\n result[k] = parseEvaluationResultValue(v, handles, refs);\n }\n return result;\n }\n if ("h" in value)\n return handles[value.h];\n if ("ta" in value)\n return base64ToTypedArray(value.ta.b, typedArrayConstructors[value.ta.k]);\n if ("ab" in value)\n return base64ToTypedArray(value.ab.b, Uint8Array).buffer;\n }\n return value;\n}\nfunction serializeAsCallArgument(value, handleSerializer) {\n return serialize(value, handleSerializer, { visited: /* @__PURE__ */ new Map(), lastId: 0 });\n}\nfunction serialize(value, handleSerializer, visitorInfo) {\n if (value && typeof value === "object") {\n if (typeof globalThis.Window === "function" && value instanceof globalThis.Window)\n return "ref: ";\n if (typeof globalThis.Document === "function" && value instanceof globalThis.Document)\n return "ref: ";\n if (typeof globalThis.Node === "function" && value instanceof globalThis.Node)\n return "ref: ";\n }\n return innerSerialize(value, handleSerializer, visitorInfo);\n}\nfunction innerSerialize(value, handleSerializer, visitorInfo) {\n var _a;\n const result = handleSerializer(value);\n if ("fallThrough" in result)\n value = result.fallThrough;\n else\n return result;\n if (typeof value === "symbol")\n return { v: "undefined" };\n if (Object.is(value, void 0))\n return { v: "undefined" };\n if (Object.is(value, null))\n return { v: "null" };\n if (Object.is(value, NaN))\n return { v: "NaN" };\n if (Object.is(value, Infinity))\n return { v: "Infinity" };\n if (Object.is(value, -Infinity))\n return { v: "-Infinity" };\n if (Object.is(value, -0))\n return { v: "-0" };\n if (typeof value === "boolean")\n return value;\n if (typeof value === "number")\n return value;\n if (typeof value === "string")\n return value;\n if (typeof value === "bigint")\n return { bi: value.toString() };\n if (isError(value)) {\n let stack;\n if ((_a = value.stack) == null ? void 0 : _a.startsWith(value.name + ": " + value.message)) {\n stack = value.stack;\n } else {\n stack = `${value.name}: ${value.message}\n${value.stack}`;\n }\n return { e: { n: value.name, m: value.message, s: stack } };\n }\n if (isDate(value))\n return { d: value.toJSON() };\n if (isURL(value))\n return { u: value.toJSON() };\n if (isRegExp(value))\n return { r: { p: value.source, f: value.flags } };\n for (const [k, ctor] of Object.entries(typedArrayConstructors)) {\n if (isTypedArray(value, ctor))\n return { ta: { b: typedArrayToBase64(value), k } };\n }\n if (isArrayBuffer(value))\n return { ab: { b: typedArrayToBase64(new Uint8Array(value)) } };\n const id = visitorInfo.visited.get(value);\n if (id)\n return { ref: id };\n if (Array.isArray(value)) {\n const a = [];\n const id2 = ++visitorInfo.lastId;\n visitorInfo.visited.set(value, id2);\n for (let i = 0; i < value.length; ++i)\n a.push(serialize(value[i], handleSerializer, visitorInfo));\n return { a, id: id2 };\n }\n if (typeof value === "object") {\n const o = [];\n const id2 = ++visitorInfo.lastId;\n visitorInfo.visited.set(value, id2);\n for (const name of Object.keys(value)) {\n let item;\n try {\n item = value[name];\n } catch (e) {\n continue;\n }\n if (name === "toJSON" && typeof item === "function")\n o.push({ k: name, v: { o: [], id: 0 } });\n else\n o.push({ k: name, v: serialize(item, handleSerializer, visitorInfo) });\n }\n let jsonWrapper;\n try {\n if (o.length === 0 && value.toJSON && typeof value.toJSON === "function")\n jsonWrapper = { value: value.toJSON() };\n } catch (e) {\n }\n if (jsonWrapper)\n return innerSerialize(jsonWrapper.value, handleSerializer, visitorInfo);\n return { o, id: id2 };\n }\n}\n\n// packages/injected/src/utilityScript.ts\nvar UtilityScript = class {\n constructor(global, isUnderTest) {\n var _a, _b, _c, _d, _e, _f, _g, _h;\n this.global = global;\n this.isUnderTest = isUnderTest;\n if (global.__pwClock) {\n this.builtins = global.__pwClock.builtins;\n } else {\n this.builtins = {\n setTimeout: (_a = global.setTimeout) == null ? void 0 : _a.bind(global),\n clearTimeout: (_b = global.clearTimeout) == null ? void 0 : _b.bind(global),\n setInterval: (_c = global.setInterval) == null ? void 0 : _c.bind(global),\n clearInterval: (_d = global.clearInterval) == null ? void 0 : _d.bind(global),\n requestAnimationFrame: (_e = global.requestAnimationFrame) == null ? void 0 : _e.bind(global),\n cancelAnimationFrame: (_f = global.cancelAnimationFrame) == null ? void 0 : _f.bind(global),\n requestIdleCallback: (_g = global.requestIdleCallback) == null ? void 0 : _g.bind(global),\n cancelIdleCallback: (_h = global.cancelIdleCallback) == null ? void 0 : _h.bind(global),\n performance: global.performance,\n Intl: global.Intl,\n Date: global.Date,\n AbortSignal: global.AbortSignal\n };\n }\n if (this.isUnderTest)\n global.builtins = this.builtins;\n }\n evaluate(isFunction, returnByValue, expression, argCount, ...argsAndHandles) {\n const args = argsAndHandles.slice(0, argCount);\n const handles = argsAndHandles.slice(argCount);\n const parameters = [];\n for (let i = 0; i < args.length; i++)\n parameters[i] = parseEvaluationResultValue(args[i], handles);\n let result = this.global.eval(expression);\n if (isFunction === true) {\n result = result(...parameters);\n } else if (isFunction === false) {\n result = result;\n } else {\n if (typeof result === "function")\n result = result(...parameters);\n }\n return returnByValue ? this._promiseAwareJsonValueNoThrow(result) : result;\n }\n jsonValue(returnByValue, value) {\n if (value === void 0)\n return void 0;\n return serializeAsCallArgument(value, (value2) => ({ fallThrough: value2 }));\n }\n _promiseAwareJsonValueNoThrow(value) {\n const safeJson = (value2) => {\n try {\n return this.jsonValue(true, value2);\n } catch (e) {\n return void 0;\n }\n };\n if (value && typeof value === "object" && typeof value.then === "function") {\n return (async () => {\n const promiseValue = await value;\n return safeJson(promiseValue);\n })();\n }\n return safeJson(value);\n }\n};\n'; + } +}); + +// packages/playwright-core/src/server/javascript.ts +async function evaluate(context2, returnByValue, pageFunction, ...args) { + return evaluateExpression(context2, String(pageFunction), { returnByValue, isFunction: typeof pageFunction === "function" }, ...args); +} +async function evaluateExpression(context2, expression2, options, ...args) { + expression2 = normalizeEvaluationExpression(expression2, options.isFunction); + const handles = []; + const toDispose = []; + const pushHandle = (handle) => { + handles.push(handle); + return handles.length - 1; + }; + args = args.map((arg) => serializeAsCallArgument(arg, (handle) => { + if (handle instanceof JSHandle) { + if (!handle._objectId) + return { fallThrough: handle._value }; + if (handle._disposed) + throw new JavaScriptErrorInEvaluate("JSHandle is disposed!"); + const adopted = context2.adoptIfNeeded(handle); + if (adopted === null) + return { h: pushHandle(Promise.resolve(handle)) }; + toDispose.push(adopted); + return { h: pushHandle(adopted) }; + } + return { fallThrough: handle }; + })); + const utilityScriptObjects = []; + for (const handle of await Promise.all(handles)) { + if (handle._context !== context2) + throw new JavaScriptErrorInEvaluate("JSHandles can be evaluated only in the context they were created!"); + utilityScriptObjects.push(handle); + } + const utilityScriptValues = [options.isFunction, options.returnByValue, expression2, args.length, ...args]; + const script = `(utilityScript, ...args) => utilityScript.evaluate(...args)`; + try { + return await context2._evaluateWithArguments(script, options.returnByValue || false, utilityScriptValues, utilityScriptObjects); + } finally { + toDispose.map((handlePromise) => handlePromise.then((handle) => handle.dispose())); + } +} +function parseUnserializableValue(unserializableValue) { + if (unserializableValue === "NaN") + return NaN; + if (unserializableValue === "Infinity") + return Infinity; + if (unserializableValue === "-Infinity") + return -Infinity; + if (unserializableValue === "-0") + return -0; +} +function normalizeEvaluationExpression(expression2, isFunction2) { + expression2 = expression2.trim(); + if (isFunction2) { + try { + new Function("(" + expression2 + ")"); + } catch (e1) { + if (expression2.startsWith("async ")) + expression2 = "async function " + expression2.substring("async ".length); + else + expression2 = "function " + expression2; + try { + new Function("(" + expression2 + ")"); + } catch (e2) { + throw new Error("Passed function is not well-serializable!"); + } + } + } + if (/^(async)?\s*function(\s|\()/.test(expression2)) + expression2 = "(" + expression2 + ")"; + return expression2; +} +function isJavaScriptErrorInEvaluate(error) { + return error instanceof JavaScriptErrorInEvaluate; +} +function sparseArrayToString(entries) { + const arrayEntries = []; + for (const { name, value: value2 } of entries) { + const index = +name; + if (isNaN(index) || index < 0) + continue; + arrayEntries.push({ index, value: value2 }); + } + arrayEntries.sort((a, b) => a.index - b.index); + let lastIndex = -1; + const tokens = []; + for (const { index, value: value2 } of arrayEntries) { + const emptyItems = index - lastIndex - 1; + if (emptyItems === 1) + tokens.push(`empty`); + else if (emptyItems > 1) + tokens.push(`empty x ${emptyItems}`); + tokens.push(String(value2)); + lastIndex = index; + } + return "[" + tokens.join(", ") + "]"; +} +var ExecutionContext, JSHandle, JavaScriptErrorInEvaluate, snapshottedFunctionBuiltins, snapshottedObjectBuiltins, snapshottedTimerBuiltins, saveGlobalsSnapshotSource, mainWorldGlobalsSnapshotSource; +var init_javascript = __esm({ + "packages/playwright-core/src/server/javascript.ts"() { + "use strict"; + init_utilityScriptSerializers(); + init_manualPromise(); + init_debug(); + init_instrumentation(); + init_utilityScriptSource(); + ExecutionContext = class extends SdkObject { + constructor(parent, delegate, worldNameForTest, options) { + super(parent, "execution-context"); + this._contextDestroyedScope = new LongStandingScope(); + this.worldNameForTest = worldNameForTest; + this._noUtilityWorld = options?.noUtilityWorld; + this.delegate = delegate; + } + contextDestroyed(reason) { + this._contextDestroyedScope.close(new Error(reason)); + } + async raceAgainstContextDestroyed(promise) { + return this._contextDestroyedScope.race(promise); + } + rawEvaluateJSON(expression2) { + return this.raceAgainstContextDestroyed(this.delegate.rawEvaluateJSON(expression2)); + } + rawEvaluateHandle(expression2) { + return this.raceAgainstContextDestroyed(this.delegate.rawEvaluateHandle(this, expression2)); + } + async _evaluateWithArguments(expression2, returnByValue, values, handles) { + const utilityScript = await this._utilityScript(); + return this.raceAgainstContextDestroyed(this.delegate.evaluateWithArguments(expression2, returnByValue, utilityScript, values, handles)); + } + getProperties(object) { + return this.raceAgainstContextDestroyed(this.delegate.getProperties(object)); + } + _releaseHandle(handle) { + return this.delegate.releaseHandle(handle); + } + adoptIfNeeded(handle) { + return null; + } + _utilityScript() { + if (!this._utilityScriptPromise) { + const globalsSnapshot = this._noUtilityWorld ? mainWorldGlobalsSnapshotSource : ""; + const source11 = ` + (() => { + ${globalsSnapshot} + const module = {}; + ${source3} + return new (module.exports.UtilityScript())(globalThis, ${isUnderTest()}); + })();`; + this._utilityScriptPromise = this.raceAgainstContextDestroyed(this.delegate.rawEvaluateHandle(this, source11)).then((handle) => { + handle._setPreview("UtilityScript"); + return handle; + }); + } + return this._utilityScriptPromise; + } + }; + JSHandle = class extends SdkObject { + constructor(context2, type3, preview, objectId, value2) { + super(context2, "handle"); + this.__jshandle = true; + this._disposed = false; + this._context = context2; + this._objectId = objectId; + this._value = value2; + this._objectType = type3; + this._preview = this._objectId ? preview || `JSHandle@${this._objectType}` : String(value2); + if (this._objectId && globalThis.leakedJSHandles) + globalThis.leakedJSHandles.set(this, new Error("Leaked JSHandle")); + } + async evaluateExpression(progress2, expression2, options, arg) { + return await progress2.race(this.internalEvaluateExpression(expression2, options, arg)); + } + async evaluateExpressionHandle(progress2, expression2, options, arg) { + return await progress2.race(this._evaluateExpressionHandle(expression2, options, arg)); + } + async getProperty(progress2, propertyName) { + return await progress2.race(this._getProperty(propertyName)); + } + async getProperties(progress2) { + return await progress2.race(this.internalGetProperties()); + } + async jsonValue(progress2) { + return await progress2.race(this._jsonValue()); + } + async evaluate(pageFunction, arg) { + return evaluate(this._context, true, pageFunction, this, arg); + } + async evaluateHandle(pageFunction, arg) { + return evaluate(this._context, false, pageFunction, this, arg); + } + async internalEvaluateExpression(expression2, options, arg) { + return await evaluateExpression(this._context, expression2, { ...options, returnByValue: true }, this, arg); + } + async _evaluateExpressionHandle(expression2, options, arg) { + return await evaluateExpression(this._context, expression2, { ...options, returnByValue: false }, this, arg); + } + async _getProperty(propertyName) { + const objectHandle = await this.evaluateHandle((object, propertyName2) => { + const result3 = { __proto__: null }; + result3[propertyName2] = object[propertyName2]; + return result3; + }, propertyName); + const properties = await objectHandle.internalGetProperties(); + const result2 = properties.get(propertyName); + objectHandle.dispose(); + return result2; + } + async internalGetProperties() { + if (!this._objectId) + return /* @__PURE__ */ new Map(); + return this._context.getProperties(this); + } + rawValue() { + return this._value; + } + async _jsonValue() { + if (!this._objectId) + return this._value; + const script = `(utilityScript, ...args) => utilityScript.jsonValue(...args)`; + return this._context._evaluateWithArguments(script, true, [true], [this]); + } + asElement() { + return null; + } + dispose() { + if (this._disposed) + return; + this._disposed = true; + if (this._objectId) { + this._context._releaseHandle(this).catch((e) => { + }); + if (globalThis.leakedJSHandles) + globalThis.leakedJSHandles.delete(this); + } + } + toString() { + return this._preview; + } + _setPreviewCallback(callback) { + this._previewCallback = callback; + } + preview() { + return this._preview; + } + worldNameForTest() { + return this._context.worldNameForTest; + } + _setPreview(preview) { + this._preview = preview; + if (this._previewCallback) + this._previewCallback(preview); + } + }; + JavaScriptErrorInEvaluate = class extends Error { + }; + snapshottedFunctionBuiltins = [ + // DOM + "Node", + "Element", + "NodeFilter", + "HTMLElement", + "Document", + "ShadowRoot", + "MutationObserver", + "Event", + "CustomEvent", + "EventTarget", + // JS standard + "Map", + "Set", + "WeakMap", + "WeakSet", + "Promise", + "Symbol", + "Error", + "TypeError", + "RegExp", + "Array", + "Object" + ]; + snapshottedObjectBuiltins = ["JSON", "Math"]; + snapshottedTimerBuiltins = ["setTimeout"]; + saveGlobalsSnapshotSource = `window.__pwSnapshotGlobals = { +${[...snapshottedFunctionBuiltins, ...snapshottedObjectBuiltins, ...snapshottedTimerBuiltins].map((n) => ` ${n}: window.${n}`).join(",\n")} +};`; + mainWorldGlobalsSnapshotSource = ` + const __snap = globalThis.__pwSnapshotGlobals || {}; +${snapshottedFunctionBuiltins.map((n) => ` const ${n} = (typeof globalThis.${n} === 'function' ? globalThis.${n} : __snap.${n});`).join("\n")} +${snapshottedObjectBuiltins.map((n) => ` const ${n} = (typeof globalThis.${n} === 'object' && globalThis.${n} ? globalThis.${n} : __snap.${n});`).join("\n")} +`; + } +}); + +// packages/playwright-core/src/server/fileUploadUtils.ts +async function filesExceedUploadLimit(files) { + const sizes = await Promise.all(files.map(async (file) => (await import_fs13.default.promises.stat(file)).size)); + return sizes.reduce((total, size) => total + size, 0) >= fileUploadSizeLimit; +} +async function prepareFilesForUpload(frame, params2) { + const { payloads, streams, directoryStream } = params2; + let { localPaths, localDirectory } = params2; + if (localPaths && !frame.attribution.playwright.options.isClientCollocatedWithServer) + throw new Error("localPaths are not allowed when the client is not local"); + if ([payloads, localPaths, localDirectory, streams, directoryStream].filter(Boolean).length !== 1) + throw new Error("Exactly one of payloads, localPaths and streams must be provided"); + if (streams) + localPaths = streams.map((c) => c.path()); + if (directoryStream) + localDirectory = directoryStream.path(); + if (localPaths) { + for (const p of localPaths) + assert(import_path12.default.isAbsolute(p) && import_path12.default.resolve(p) === p, "Paths provided to localPaths must be absolute and fully resolved."); + } + let fileBuffers = payloads; + if (!frame._page.browserContext._browser._isBrowserCollocatedWithServer) { + if (localPaths) { + if (await filesExceedUploadLimit(localPaths)) + throw new Error("Cannot transfer files larger than 50Mb to a browser not co-located with the server"); + fileBuffers = await Promise.all(localPaths.map(async (item) => { + return { + name: import_path12.default.basename(item), + buffer: await import_fs13.default.promises.readFile(item), + lastModifiedMs: (await import_fs13.default.promises.stat(item)).mtimeMs + }; + })); + localPaths = void 0; + } + } + const filePayloads = fileBuffers?.map((payload) => ({ + name: payload.name, + mimeType: payload.mimeType || mime4.getType(payload.name) || "application/octet-stream", + buffer: payload.buffer.toString("base64"), + lastModifiedMs: payload.lastModifiedMs + })); + return { localPaths, localDirectory, filePayloads }; +} +var import_fs13, import_path12, mime4, fileUploadSizeLimit; +var init_fileUploadUtils = __esm({ + "packages/playwright-core/src/server/fileUploadUtils.ts"() { + "use strict"; + import_fs13 = __toESM(require("fs")); + import_path12 = __toESM(require("path")); + init_assert(); + mime4 = require("./utilsBundle").mime; + fileUploadSizeLimit = 50 * 1024 * 1024; + } +}); + +// packages/playwright-core/src/generated/injectedScriptSource.ts +var source4; +var init_injectedScriptSource = __esm({ + "packages/playwright-core/src/generated/injectedScriptSource.ts"() { + "use strict"; + source4 = '\nvar __commonJS = obj => {\n let required = false;\n let result;\n return function __require() {\n if (!required) {\n required = true;\n let fn;\n for (const name in obj) { fn = obj[name]; break; }\n const module = { exports: {} };\n fn(module.exports, module);\n result = module.exports;\n }\n return result;\n }\n};\nvar __export = (target, all) => {for (var name in all) target[name] = all[name];};\nvar __toESM = mod => ({ ...mod, \'default\': mod });\nvar __toCommonJS = mod => ({ ...mod, __esModule: true });\n\n\n// packages/injected/src/injectedScript.ts\nvar injectedScript_exports = {};\n__export(injectedScript_exports, {\n InjectedScript: () => InjectedScript\n});\nmodule.exports = __toCommonJS(injectedScript_exports);\n\n// packages/isomorphic/ariaSnapshot.ts\nfunction ariaNodesEqual(a, b) {\n if (a.role !== b.role || a.name !== b.name)\n return false;\n if (!ariaPropsEqual(a, b) || hasPointerCursor(a) !== hasPointerCursor(b))\n return false;\n const aKeys = Object.keys(a.props);\n const bKeys = Object.keys(b.props);\n return aKeys.length === bKeys.length && aKeys.every((k) => a.props[k] === b.props[k]);\n}\nfunction hasPointerCursor(ariaNode) {\n return ariaNode.box.cursor === "pointer";\n}\nfunction ariaPropsEqual(a, b) {\n return a.active === b.active && a.checked === b.checked && a.disabled === b.disabled && a.expanded === b.expanded && a.invalid === b.invalid && a.selected === b.selected && a.level === b.level && a.pressed === b.pressed;\n}\nfunction parseAriaSnapshot(yaml, text, options = {}) {\n var _a;\n const lineCounter = new yaml.LineCounter();\n const parseOptions = {\n keepSourceTokens: true,\n lineCounter,\n ...options\n };\n const yamlDoc = yaml.parseDocument(text, parseOptions);\n const errors = [];\n const convertRange = (range) => {\n return [lineCounter.linePos(range[0]), lineCounter.linePos(range[1])];\n };\n const addError = (error) => {\n errors.push({\n message: error.message,\n range: [lineCounter.linePos(error.pos[0]), lineCounter.linePos(error.pos[1])]\n });\n };\n const convertSeq = (container, seq) => {\n for (const item of seq.items) {\n const itemIsString = item instanceof yaml.Scalar && typeof item.value === "string";\n if (itemIsString) {\n const childNode = KeyParser.parse(item, parseOptions, errors);\n if (childNode) {\n container.children = container.children || [];\n container.children.push(childNode);\n }\n continue;\n }\n const itemIsMap = item instanceof yaml.YAMLMap;\n if (itemIsMap) {\n convertMap(container, item);\n continue;\n }\n errors.push({\n message: "Sequence items should be strings or maps",\n range: convertRange(item.range || seq.range)\n });\n }\n };\n const convertMap = (container, map) => {\n var _a2;\n for (const entry of map.items) {\n container.children = container.children || [];\n const keyIsString = entry.key instanceof yaml.Scalar && typeof entry.key.value === "string";\n if (!keyIsString) {\n errors.push({\n message: "Only string keys are supported",\n range: convertRange(entry.key.range || map.range)\n });\n continue;\n }\n const key = entry.key;\n const value = entry.value;\n if (key.value === "text") {\n const valueIsString = value instanceof yaml.Scalar && typeof value.value === "string";\n if (!valueIsString) {\n errors.push({\n message: "Text value should be a string",\n range: convertRange(entry.value.range || map.range)\n });\n continue;\n }\n container.children.push({\n kind: "text",\n text: textValue(value.value)\n });\n continue;\n }\n if (key.value === "/children") {\n const valueIsString = value instanceof yaml.Scalar && typeof value.value === "string";\n if (!valueIsString || value.value !== "contain" && value.value !== "equal" && value.value !== "deep-equal") {\n errors.push({\n message: \'Strict value should be "contain", "equal" or "deep-equal"\',\n range: convertRange(entry.value.range || map.range)\n });\n continue;\n }\n container.containerMode = value.value;\n continue;\n }\n if (key.value.startsWith("/")) {\n const valueIsString = value instanceof yaml.Scalar && typeof value.value === "string";\n if (!valueIsString) {\n errors.push({\n message: "Property value should be a string",\n range: convertRange(entry.value.range || map.range)\n });\n continue;\n }\n container.props = (_a2 = container.props) != null ? _a2 : {};\n container.props[key.value.slice(1)] = textValue(value.value);\n continue;\n }\n const childNode = KeyParser.parse(key, parseOptions, errors);\n if (!childNode)\n continue;\n const valueIsScalar = value instanceof yaml.Scalar;\n if (valueIsScalar) {\n const type = typeof value.value;\n if (type !== "string" && type !== "number" && type !== "boolean") {\n errors.push({\n message: "Node value should be a string or a sequence",\n range: convertRange(entry.value.range || map.range)\n });\n continue;\n }\n container.children.push({\n ...childNode,\n children: [{\n kind: "text",\n text: textValue(String(value.value))\n }]\n });\n continue;\n }\n const valueIsSequence = value instanceof yaml.YAMLSeq;\n if (valueIsSequence) {\n container.children.push(childNode);\n convertSeq(childNode, value);\n continue;\n }\n errors.push({\n message: "Map values should be strings or sequences",\n range: convertRange(entry.value.range || map.range)\n });\n }\n };\n const fragment = { kind: "role", role: "fragment" };\n yamlDoc.errors.forEach(addError);\n if (errors.length)\n return { errors, fragment };\n if (!(yamlDoc.contents instanceof yaml.YAMLSeq)) {\n errors.push({\n message: \'Aria snapshot must be a YAML sequence, elements starting with " -"\',\n range: yamlDoc.contents ? convertRange(yamlDoc.contents.range) : [{ line: 0, col: 0 }, { line: 0, col: 0 }]\n });\n }\n if (errors.length)\n return { errors, fragment };\n convertSeq(fragment, yamlDoc.contents);\n if (errors.length)\n return { errors, fragment: emptyFragment };\n if (((_a = fragment.children) == null ? void 0 : _a.length) === 1 && (!fragment.containerMode || fragment.containerMode === "contain"))\n return { fragment: fragment.children[0], errors: [] };\n return { fragment, errors: [] };\n}\nvar emptyFragment = { kind: "role", role: "fragment" };\nfunction normalizeWhitespace(text) {\n return text.replace(/[\\u200b\\u00ad]/g, "").replace(/[\\r\\n\\s\\t]+/g, " ").trim();\n}\nfunction textValue(value) {\n return {\n raw: value,\n normalized: normalizeWhitespace(value)\n };\n}\nvar KeyParser = class _KeyParser {\n static parse(text, options, errors) {\n try {\n return new _KeyParser(text.value)._parse();\n } catch (e) {\n if (e instanceof ParserError) {\n const message = options.prettyErrors === false ? e.message : e.message + ":\\n\\n" + text.value + "\\n" + " ".repeat(e.pos) + "^\\n";\n errors.push({\n message,\n range: [options.lineCounter.linePos(text.range[0]), options.lineCounter.linePos(text.range[0] + e.pos)]\n });\n return null;\n }\n throw e;\n }\n }\n constructor(input) {\n this._input = input;\n this._pos = 0;\n this._length = input.length;\n }\n _peek() {\n return this._input[this._pos] || "";\n }\n _next() {\n if (this._pos < this._length)\n return this._input[this._pos++];\n return null;\n }\n _eof() {\n return this._pos >= this._length;\n }\n _isWhitespace() {\n return !this._eof() && /\\s/.test(this._peek());\n }\n _skipWhitespace() {\n while (this._isWhitespace())\n this._pos++;\n }\n _readIdentifier(type) {\n if (this._eof())\n this._throwError(`Unexpected end of input when expecting ${type}`);\n const start = this._pos;\n while (!this._eof() && /[a-zA-Z]/.test(this._peek()))\n this._pos++;\n return this._input.slice(start, this._pos);\n }\n _readString() {\n let result = "";\n let escaped = false;\n while (!this._eof()) {\n const ch = this._next();\n if (escaped) {\n result += ch;\n escaped = false;\n } else if (ch === "\\\\") {\n escaped = true;\n } else if (ch === \'"\') {\n return result;\n } else {\n result += ch;\n }\n }\n this._throwError("Unterminated string");\n }\n _throwError(message, offset = 0) {\n throw new ParserError(message, offset || this._pos);\n }\n _readRegex() {\n let result = "";\n let escaped = false;\n let insideClass = false;\n while (!this._eof()) {\n const ch = this._next();\n if (escaped) {\n result += ch;\n escaped = false;\n } else if (ch === "\\\\") {\n escaped = true;\n result += ch;\n } else if (ch === "/" && !insideClass) {\n return { pattern: result };\n } else if (ch === "[") {\n insideClass = true;\n result += ch;\n } else if (ch === "]" && insideClass) {\n result += ch;\n insideClass = false;\n } else {\n result += ch;\n }\n }\n this._throwError("Unterminated regex");\n }\n _readStringOrRegex() {\n const ch = this._peek();\n if (ch === \'"\') {\n this._next();\n return normalizeWhitespace(this._readString());\n }\n if (ch === "/") {\n this._next();\n return this._readRegex();\n }\n return null;\n }\n _readAttributes(result) {\n let errorPos = this._pos;\n while (true) {\n this._skipWhitespace();\n if (this._peek() === "[") {\n this._next();\n this._skipWhitespace();\n errorPos = this._pos;\n const flagName = this._readIdentifier("attribute");\n this._skipWhitespace();\n let flagValue = "";\n if (this._peek() === "=") {\n this._next();\n this._skipWhitespace();\n errorPos = this._pos;\n while (this._peek() !== "]" && !this._isWhitespace() && !this._eof())\n flagValue += this._next();\n }\n this._skipWhitespace();\n if (this._peek() !== "]")\n this._throwError("Expected ]");\n this._next();\n this._applyAttribute(result, flagName, flagValue || "true", errorPos);\n } else {\n break;\n }\n }\n }\n _parse() {\n this._skipWhitespace();\n const role = this._readIdentifier("role");\n this._skipWhitespace();\n const name = this._readStringOrRegex() || "";\n const result = { kind: "role", role, name };\n this._readAttributes(result);\n this._skipWhitespace();\n if (!this._eof())\n this._throwError("Unexpected input");\n return result;\n }\n _applyAttribute(node, key, value, errorPos) {\n if (key === "checked") {\n this._assert(value === "true" || value === "false" || value === "mixed", \'Value of "checked" attribute must be a boolean or "mixed"\', errorPos);\n node.checked = value === "true" ? true : value === "false" ? false : "mixed";\n return;\n }\n if (key === "disabled") {\n this._assert(value === "true" || value === "false", \'Value of "disabled" attribute must be a boolean\', errorPos);\n node.disabled = value === "true";\n return;\n }\n if (key === "expanded") {\n this._assert(value === "true" || value === "false", \'Value of "expanded" attribute must be a boolean\', errorPos);\n node.expanded = value === "true";\n return;\n }\n if (key === "active") {\n this._assert(value === "true" || value === "false", \'Value of "active" attribute must be a boolean\', errorPos);\n node.active = value === "true";\n return;\n }\n if (key === "invalid") {\n this._assert(value === "true" || value === "false" || value === "grammar" || value === "spelling", \'Value of "invalid" attribute must be a boolean, "grammar" or "spelling"\', errorPos);\n node.invalid = value === "true" ? true : value === "false" ? false : value;\n return;\n }\n if (key === "level") {\n this._assert(!isNaN(Number(value)), \'Value of "level" attribute must be a number\', errorPos);\n node.level = Number(value);\n return;\n }\n if (key === "pressed") {\n this._assert(value === "true" || value === "false" || value === "mixed", \'Value of "pressed" attribute must be a boolean or "mixed"\', errorPos);\n node.pressed = value === "true" ? true : value === "false" ? false : "mixed";\n return;\n }\n if (key === "selected") {\n this._assert(value === "true" || value === "false", \'Value of "selected" attribute must be a boolean\', errorPos);\n node.selected = value === "true";\n return;\n }\n this._assert(false, `Unsupported attribute [${key}]`, errorPos);\n }\n _assert(value, message, valuePos) {\n if (!value)\n this._throwError(message || "Assertion error", valuePos);\n }\n};\nvar ParserError = class extends Error {\n constructor(message, pos) {\n super(message);\n this.pos = pos;\n }\n};\nfunction findNewNode(from, to) {\n var _a, _b;\n function fillMap(root, map, position) {\n let size = 1;\n let childPosition = position + size;\n for (const child of root.children || []) {\n if (typeof child === "string") {\n size++;\n childPosition++;\n } else {\n size += fillMap(child, map, childPosition);\n childPosition += size;\n }\n }\n if (!["none", "presentation", "fragment", "iframe", "generic"].includes(root.role) && root.name) {\n let byRole = map.get(root.role);\n if (!byRole) {\n byRole = /* @__PURE__ */ new Map();\n map.set(root.role, byRole);\n }\n const existing = byRole.get(root.name);\n const sizeAndPosition = size * 100 - position;\n if (!existing || existing.sizeAndPosition < sizeAndPosition)\n byRole.set(root.name, { node: root, sizeAndPosition });\n }\n return size;\n }\n const fromMap = /* @__PURE__ */ new Map();\n if (from)\n fillMap(from, fromMap, 0);\n const toMap = /* @__PURE__ */ new Map();\n fillMap(to, toMap, 0);\n const result = [];\n for (const [role, byRole] of toMap) {\n for (const [name, byName] of byRole) {\n const inFrom = (_a = fromMap.get(role)) == null ? void 0 : _a.get(name);\n if (!inFrom)\n result.push(byName);\n }\n }\n result.sort((a, b) => b.sizeAndPosition - a.sizeAndPosition);\n return (_b = result[0]) == null ? void 0 : _b.node;\n}\n\n// packages/isomorphic/cssTokenizer.ts\nvar between = function(num, first, last) {\n return num >= first && num <= last;\n};\nfunction digit(code) {\n return between(code, 48, 57);\n}\nfunction hexdigit(code) {\n return digit(code) || between(code, 65, 70) || between(code, 97, 102);\n}\nfunction uppercaseletter(code) {\n return between(code, 65, 90);\n}\nfunction lowercaseletter(code) {\n return between(code, 97, 122);\n}\nfunction letter(code) {\n return uppercaseletter(code) || lowercaseletter(code);\n}\nfunction nonascii(code) {\n return code >= 128;\n}\nfunction namestartchar(code) {\n return letter(code) || nonascii(code) || code === 95;\n}\nfunction namechar(code) {\n return namestartchar(code) || digit(code) || code === 45;\n}\nfunction nonprintable(code) {\n return between(code, 0, 8) || code === 11 || between(code, 14, 31) || code === 127;\n}\nfunction newline(code) {\n return code === 10;\n}\nfunction whitespace(code) {\n return newline(code) || code === 9 || code === 32;\n}\nvar maximumallowedcodepoint = 1114111;\nvar InvalidCharacterError = class extends Error {\n constructor(message) {\n super(message);\n this.name = "InvalidCharacterError";\n }\n};\nfunction preprocess(str) {\n const codepoints = [];\n for (let i = 0; i < str.length; i++) {\n let code = str.charCodeAt(i);\n if (code === 13 && str.charCodeAt(i + 1) === 10) {\n code = 10;\n i++;\n }\n if (code === 13 || code === 12)\n code = 10;\n if (code === 0)\n code = 65533;\n if (between(code, 55296, 56319) && between(str.charCodeAt(i + 1), 56320, 57343)) {\n const lead = code - 55296;\n const trail = str.charCodeAt(i + 1) - 56320;\n code = Math.pow(2, 16) + lead * Math.pow(2, 10) + trail;\n i++;\n }\n codepoints.push(code);\n }\n return codepoints;\n}\nfunction stringFromCode(code) {\n if (code <= 65535)\n return String.fromCharCode(code);\n code -= Math.pow(2, 16);\n const lead = Math.floor(code / Math.pow(2, 10)) + 55296;\n const trail = code % Math.pow(2, 10) + 56320;\n return String.fromCharCode(lead) + String.fromCharCode(trail);\n}\nfunction tokenize(str1) {\n const str = preprocess(str1);\n let i = -1;\n const tokens = [];\n let code;\n let line = 0;\n let column = 0;\n let lastLineLength = 0;\n const incrLineno = function() {\n line += 1;\n lastLineLength = column;\n column = 0;\n };\n const locStart = { line, column };\n const codepoint = function(i2) {\n if (i2 >= str.length)\n return -1;\n return str[i2];\n };\n const next = function(num) {\n if (num === void 0)\n num = 1;\n if (num > 3)\n throw "Spec Error: no more than three codepoints of lookahead.";\n return codepoint(i + num);\n };\n const consume = function(num) {\n if (num === void 0)\n num = 1;\n i += num;\n code = codepoint(i);\n if (newline(code))\n incrLineno();\n else\n column += num;\n return true;\n };\n const reconsume = function() {\n i -= 1;\n if (newline(code)) {\n line -= 1;\n column = lastLineLength;\n } else {\n column -= 1;\n }\n locStart.line = line;\n locStart.column = column;\n return true;\n };\n const eof = function(codepoint2) {\n if (codepoint2 === void 0)\n codepoint2 = code;\n return codepoint2 === -1;\n };\n const donothing = function() {\n };\n const parseerror = function() {\n };\n const consumeAToken = function() {\n consumeComments();\n consume();\n if (whitespace(code)) {\n while (whitespace(next()))\n consume();\n return new WhitespaceToken();\n } else if (code === 34) {\n return consumeAStringToken();\n } else if (code === 35) {\n if (namechar(next()) || areAValidEscape(next(1), next(2))) {\n const token = new HashToken("");\n if (wouldStartAnIdentifier(next(1), next(2), next(3)))\n token.type = "id";\n token.value = consumeAName();\n return token;\n } else {\n return new DelimToken(code);\n }\n } else if (code === 36) {\n if (next() === 61) {\n consume();\n return new SuffixMatchToken();\n } else {\n return new DelimToken(code);\n }\n } else if (code === 39) {\n return consumeAStringToken();\n } else if (code === 40) {\n return new OpenParenToken();\n } else if (code === 41) {\n return new CloseParenToken();\n } else if (code === 42) {\n if (next() === 61) {\n consume();\n return new SubstringMatchToken();\n } else {\n return new DelimToken(code);\n }\n } else if (code === 43) {\n if (startsWithANumber()) {\n reconsume();\n return consumeANumericToken();\n } else {\n return new DelimToken(code);\n }\n } else if (code === 44) {\n return new CommaToken();\n } else if (code === 45) {\n if (startsWithANumber()) {\n reconsume();\n return consumeANumericToken();\n } else if (next(1) === 45 && next(2) === 62) {\n consume(2);\n return new CDCToken();\n } else if (startsWithAnIdentifier()) {\n reconsume();\n return consumeAnIdentlikeToken();\n } else {\n return new DelimToken(code);\n }\n } else if (code === 46) {\n if (startsWithANumber()) {\n reconsume();\n return consumeANumericToken();\n } else {\n return new DelimToken(code);\n }\n } else if (code === 58) {\n return new ColonToken();\n } else if (code === 59) {\n return new SemicolonToken();\n } else if (code === 60) {\n if (next(1) === 33 && next(2) === 45 && next(3) === 45) {\n consume(3);\n return new CDOToken();\n } else {\n return new DelimToken(code);\n }\n } else if (code === 64) {\n if (wouldStartAnIdentifier(next(1), next(2), next(3)))\n return new AtKeywordToken(consumeAName());\n else\n return new DelimToken(code);\n } else if (code === 91) {\n return new OpenSquareToken();\n } else if (code === 92) {\n if (startsWithAValidEscape()) {\n reconsume();\n return consumeAnIdentlikeToken();\n } else {\n parseerror();\n return new DelimToken(code);\n }\n } else if (code === 93) {\n return new CloseSquareToken();\n } else if (code === 94) {\n if (next() === 61) {\n consume();\n return new PrefixMatchToken();\n } else {\n return new DelimToken(code);\n }\n } else if (code === 123) {\n return new OpenCurlyToken();\n } else if (code === 124) {\n if (next() === 61) {\n consume();\n return new DashMatchToken();\n } else if (next() === 124) {\n consume();\n return new ColumnToken();\n } else {\n return new DelimToken(code);\n }\n } else if (code === 125) {\n return new CloseCurlyToken();\n } else if (code === 126) {\n if (next() === 61) {\n consume();\n return new IncludeMatchToken();\n } else {\n return new DelimToken(code);\n }\n } else if (digit(code)) {\n reconsume();\n return consumeANumericToken();\n } else if (namestartchar(code)) {\n reconsume();\n return consumeAnIdentlikeToken();\n } else if (eof()) {\n return new EOFToken();\n } else {\n return new DelimToken(code);\n }\n };\n const consumeComments = function() {\n while (next(1) === 47 && next(2) === 42) {\n consume(2);\n while (true) {\n consume();\n if (code === 42 && next() === 47) {\n consume();\n break;\n } else if (eof()) {\n parseerror();\n return;\n }\n }\n }\n };\n const consumeANumericToken = function() {\n const num = consumeANumber();\n if (wouldStartAnIdentifier(next(1), next(2), next(3))) {\n const token = new DimensionToken();\n token.value = num.value;\n token.repr = num.repr;\n token.type = num.type;\n token.unit = consumeAName();\n return token;\n } else if (next() === 37) {\n consume();\n const token = new PercentageToken();\n token.value = num.value;\n token.repr = num.repr;\n return token;\n } else {\n const token = new NumberToken();\n token.value = num.value;\n token.repr = num.repr;\n token.type = num.type;\n return token;\n }\n };\n const consumeAnIdentlikeToken = function() {\n const str2 = consumeAName();\n if (str2.toLowerCase() === "url" && next() === 40) {\n consume();\n while (whitespace(next(1)) && whitespace(next(2)))\n consume();\n if (next() === 34 || next() === 39)\n return new FunctionToken(str2);\n else if (whitespace(next()) && (next(2) === 34 || next(2) === 39))\n return new FunctionToken(str2);\n else\n return consumeAURLToken();\n } else if (next() === 40) {\n consume();\n return new FunctionToken(str2);\n } else {\n return new IdentToken(str2);\n }\n };\n const consumeAStringToken = function(endingCodePoint) {\n if (endingCodePoint === void 0)\n endingCodePoint = code;\n let string = "";\n while (consume()) {\n if (code === endingCodePoint || eof()) {\n return new StringToken(string);\n } else if (newline(code)) {\n parseerror();\n reconsume();\n return new BadStringToken();\n } else if (code === 92) {\n if (eof(next()))\n donothing();\n else if (newline(next()))\n consume();\n else\n string += stringFromCode(consumeEscape());\n } else {\n string += stringFromCode(code);\n }\n }\n throw new Error("Internal error");\n };\n const consumeAURLToken = function() {\n const token = new URLToken("");\n while (whitespace(next()))\n consume();\n if (eof(next()))\n return token;\n while (consume()) {\n if (code === 41 || eof()) {\n return token;\n } else if (whitespace(code)) {\n while (whitespace(next()))\n consume();\n if (next() === 41 || eof(next())) {\n consume();\n return token;\n } else {\n consumeTheRemnantsOfABadURL();\n return new BadURLToken();\n }\n } else if (code === 34 || code === 39 || code === 40 || nonprintable(code)) {\n parseerror();\n consumeTheRemnantsOfABadURL();\n return new BadURLToken();\n } else if (code === 92) {\n if (startsWithAValidEscape()) {\n token.value += stringFromCode(consumeEscape());\n } else {\n parseerror();\n consumeTheRemnantsOfABadURL();\n return new BadURLToken();\n }\n } else {\n token.value += stringFromCode(code);\n }\n }\n throw new Error("Internal error");\n };\n const consumeEscape = function() {\n consume();\n if (hexdigit(code)) {\n const digits = [code];\n for (let total = 0; total < 5; total++) {\n if (hexdigit(next())) {\n consume();\n digits.push(code);\n } else {\n break;\n }\n }\n if (whitespace(next()))\n consume();\n let value = parseInt(digits.map(function(x) {\n return String.fromCharCode(x);\n }).join(""), 16);\n if (value > maximumallowedcodepoint)\n value = 65533;\n return value;\n } else if (eof()) {\n return 65533;\n } else {\n return code;\n }\n };\n const areAValidEscape = function(c1, c2) {\n if (c1 !== 92)\n return false;\n if (newline(c2))\n return false;\n return true;\n };\n const startsWithAValidEscape = function() {\n return areAValidEscape(code, next());\n };\n const wouldStartAnIdentifier = function(c1, c2, c3) {\n if (c1 === 45)\n return namestartchar(c2) || c2 === 45 || areAValidEscape(c2, c3);\n else if (namestartchar(c1))\n return true;\n else if (c1 === 92)\n return areAValidEscape(c1, c2);\n else\n return false;\n };\n const startsWithAnIdentifier = function() {\n return wouldStartAnIdentifier(code, next(1), next(2));\n };\n const wouldStartANumber = function(c1, c2, c3) {\n if (c1 === 43 || c1 === 45) {\n if (digit(c2))\n return true;\n if (c2 === 46 && digit(c3))\n return true;\n return false;\n } else if (c1 === 46) {\n if (digit(c2))\n return true;\n return false;\n } else if (digit(c1)) {\n return true;\n } else {\n return false;\n }\n };\n const startsWithANumber = function() {\n return wouldStartANumber(code, next(1), next(2));\n };\n const consumeAName = function() {\n let result = "";\n while (consume()) {\n if (namechar(code)) {\n result += stringFromCode(code);\n } else if (startsWithAValidEscape()) {\n result += stringFromCode(consumeEscape());\n } else {\n reconsume();\n return result;\n }\n }\n throw new Error("Internal parse error");\n };\n const consumeANumber = function() {\n let repr = "";\n let type = "integer";\n if (next() === 43 || next() === 45) {\n consume();\n repr += stringFromCode(code);\n }\n while (digit(next())) {\n consume();\n repr += stringFromCode(code);\n }\n if (next(1) === 46 && digit(next(2))) {\n consume();\n repr += stringFromCode(code);\n consume();\n repr += stringFromCode(code);\n type = "number";\n while (digit(next())) {\n consume();\n repr += stringFromCode(code);\n }\n }\n const c1 = next(1);\n const c2 = next(2);\n const c3 = next(3);\n if ((c1 === 69 || c1 === 101) && digit(c2)) {\n consume();\n repr += stringFromCode(code);\n consume();\n repr += stringFromCode(code);\n type = "number";\n while (digit(next())) {\n consume();\n repr += stringFromCode(code);\n }\n } else if ((c1 === 69 || c1 === 101) && (c2 === 43 || c2 === 45) && digit(c3)) {\n consume();\n repr += stringFromCode(code);\n consume();\n repr += stringFromCode(code);\n consume();\n repr += stringFromCode(code);\n type = "number";\n while (digit(next())) {\n consume();\n repr += stringFromCode(code);\n }\n }\n const value = convertAStringToANumber(repr);\n return { type, value, repr };\n };\n const convertAStringToANumber = function(string) {\n return +string;\n };\n const consumeTheRemnantsOfABadURL = function() {\n while (consume()) {\n if (code === 41 || eof()) {\n return;\n } else if (startsWithAValidEscape()) {\n consumeEscape();\n donothing();\n } else {\n donothing();\n }\n }\n };\n let iterationCount = 0;\n while (!eof(next())) {\n tokens.push(consumeAToken());\n iterationCount++;\n if (iterationCount > str.length * 2)\n throw new Error("I\'m infinite-looping!");\n }\n return tokens;\n}\nvar CSSParserToken = class {\n constructor() {\n this.tokenType = "";\n }\n toJSON() {\n return { token: this.tokenType };\n }\n toString() {\n return this.tokenType;\n }\n toSource() {\n return "" + this;\n }\n};\nvar BadStringToken = class extends CSSParserToken {\n constructor() {\n super(...arguments);\n this.tokenType = "BADSTRING";\n }\n};\nvar BadURLToken = class extends CSSParserToken {\n constructor() {\n super(...arguments);\n this.tokenType = "BADURL";\n }\n};\nvar WhitespaceToken = class extends CSSParserToken {\n constructor() {\n super(...arguments);\n this.tokenType = "WHITESPACE";\n }\n toString() {\n return "WS";\n }\n toSource() {\n return " ";\n }\n};\nvar CDOToken = class extends CSSParserToken {\n constructor() {\n super(...arguments);\n this.tokenType = "CDO";\n }\n toSource() {\n return "";\n }\n};\nvar ColonToken = class extends CSSParserToken {\n constructor() {\n super(...arguments);\n this.tokenType = ":";\n }\n};\nvar SemicolonToken = class extends CSSParserToken {\n constructor() {\n super(...arguments);\n this.tokenType = ";";\n }\n};\nvar CommaToken = class extends CSSParserToken {\n constructor() {\n super(...arguments);\n this.tokenType = ",";\n }\n};\nvar GroupingToken = class extends CSSParserToken {\n constructor() {\n super(...arguments);\n this.value = "";\n this.mirror = "";\n }\n};\nvar OpenCurlyToken = class extends GroupingToken {\n constructor() {\n super();\n this.tokenType = "{";\n this.value = "{";\n this.mirror = "}";\n }\n};\nvar CloseCurlyToken = class extends GroupingToken {\n constructor() {\n super();\n this.tokenType = "}";\n this.value = "}";\n this.mirror = "{";\n }\n};\nvar OpenSquareToken = class extends GroupingToken {\n constructor() {\n super();\n this.tokenType = "[";\n this.value = "[";\n this.mirror = "]";\n }\n};\nvar CloseSquareToken = class extends GroupingToken {\n constructor() {\n super();\n this.tokenType = "]";\n this.value = "]";\n this.mirror = "[";\n }\n};\nvar OpenParenToken = class extends GroupingToken {\n constructor() {\n super();\n this.tokenType = "(";\n this.value = "(";\n this.mirror = ")";\n }\n};\nvar CloseParenToken = class extends GroupingToken {\n constructor() {\n super();\n this.tokenType = ")";\n this.value = ")";\n this.mirror = "(";\n }\n};\nvar IncludeMatchToken = class extends CSSParserToken {\n constructor() {\n super(...arguments);\n this.tokenType = "~=";\n }\n};\nvar DashMatchToken = class extends CSSParserToken {\n constructor() {\n super(...arguments);\n this.tokenType = "|=";\n }\n};\nvar PrefixMatchToken = class extends CSSParserToken {\n constructor() {\n super(...arguments);\n this.tokenType = "^=";\n }\n};\nvar SuffixMatchToken = class extends CSSParserToken {\n constructor() {\n super(...arguments);\n this.tokenType = "$=";\n }\n};\nvar SubstringMatchToken = class extends CSSParserToken {\n constructor() {\n super(...arguments);\n this.tokenType = "*=";\n }\n};\nvar ColumnToken = class extends CSSParserToken {\n constructor() {\n super(...arguments);\n this.tokenType = "||";\n }\n};\nvar EOFToken = class extends CSSParserToken {\n constructor() {\n super(...arguments);\n this.tokenType = "EOF";\n }\n toSource() {\n return "";\n }\n};\nvar DelimToken = class extends CSSParserToken {\n constructor(code) {\n super();\n this.tokenType = "DELIM";\n this.value = "";\n this.value = stringFromCode(code);\n }\n toString() {\n return "DELIM(" + this.value + ")";\n }\n toJSON() {\n const json = this.constructor.prototype.constructor.prototype.toJSON.call(this);\n json.value = this.value;\n return json;\n }\n toSource() {\n if (this.value === "\\\\")\n return "\\\\\\n";\n else\n return this.value;\n }\n};\nvar StringValuedToken = class extends CSSParserToken {\n constructor() {\n super(...arguments);\n this.value = "";\n }\n ASCIIMatch(str) {\n return this.value.toLowerCase() === str.toLowerCase();\n }\n toJSON() {\n const json = this.constructor.prototype.constructor.prototype.toJSON.call(this);\n json.value = this.value;\n return json;\n }\n};\nvar IdentToken = class extends StringValuedToken {\n constructor(val) {\n super();\n this.tokenType = "IDENT";\n this.value = val;\n }\n toString() {\n return "IDENT(" + this.value + ")";\n }\n toSource() {\n return escapeIdent(this.value);\n }\n};\nvar FunctionToken = class extends StringValuedToken {\n constructor(val) {\n super();\n this.tokenType = "FUNCTION";\n this.value = val;\n this.mirror = ")";\n }\n toString() {\n return "FUNCTION(" + this.value + ")";\n }\n toSource() {\n return escapeIdent(this.value) + "(";\n }\n};\nvar AtKeywordToken = class extends StringValuedToken {\n constructor(val) {\n super();\n this.tokenType = "AT-KEYWORD";\n this.value = val;\n }\n toString() {\n return "AT(" + this.value + ")";\n }\n toSource() {\n return "@" + escapeIdent(this.value);\n }\n};\nvar HashToken = class extends StringValuedToken {\n constructor(val) {\n super();\n this.tokenType = "HASH";\n this.value = val;\n this.type = "unrestricted";\n }\n toString() {\n return "HASH(" + this.value + ")";\n }\n toJSON() {\n const json = this.constructor.prototype.constructor.prototype.toJSON.call(this);\n json.value = this.value;\n json.type = this.type;\n return json;\n }\n toSource() {\n if (this.type === "id")\n return "#" + escapeIdent(this.value);\n else\n return "#" + escapeHash(this.value);\n }\n};\nvar StringToken = class extends StringValuedToken {\n constructor(val) {\n super();\n this.tokenType = "STRING";\n this.value = val;\n }\n toString() {\n return \'"\' + escapeString(this.value) + \'"\';\n }\n};\nvar URLToken = class extends StringValuedToken {\n constructor(val) {\n super();\n this.tokenType = "URL";\n this.value = val;\n }\n toString() {\n return "URL(" + this.value + ")";\n }\n toSource() {\n return \'url("\' + escapeString(this.value) + \'")\';\n }\n};\nvar NumberToken = class extends CSSParserToken {\n constructor() {\n super();\n this.tokenType = "NUMBER";\n this.type = "integer";\n this.repr = "";\n }\n toString() {\n if (this.type === "integer")\n return "INT(" + this.value + ")";\n return "NUMBER(" + this.value + ")";\n }\n toJSON() {\n const json = super.toJSON();\n json.value = this.value;\n json.type = this.type;\n json.repr = this.repr;\n return json;\n }\n toSource() {\n return this.repr;\n }\n};\nvar PercentageToken = class extends CSSParserToken {\n constructor() {\n super();\n this.tokenType = "PERCENTAGE";\n this.repr = "";\n }\n toString() {\n return "PERCENTAGE(" + this.value + ")";\n }\n toJSON() {\n const json = this.constructor.prototype.constructor.prototype.toJSON.call(this);\n json.value = this.value;\n json.repr = this.repr;\n return json;\n }\n toSource() {\n return this.repr + "%";\n }\n};\nvar DimensionToken = class extends CSSParserToken {\n constructor() {\n super();\n this.tokenType = "DIMENSION";\n this.type = "integer";\n this.repr = "";\n this.unit = "";\n }\n toString() {\n return "DIM(" + this.value + "," + this.unit + ")";\n }\n toJSON() {\n const json = this.constructor.prototype.constructor.prototype.toJSON.call(this);\n json.value = this.value;\n json.type = this.type;\n json.repr = this.repr;\n json.unit = this.unit;\n return json;\n }\n toSource() {\n const source = this.repr;\n let unit = escapeIdent(this.unit);\n if (unit[0].toLowerCase() === "e" && (unit[1] === "-" || between(unit.charCodeAt(1), 48, 57))) {\n unit = "\\\\65 " + unit.slice(1, unit.length);\n }\n return source + unit;\n }\n};\nfunction escapeIdent(string) {\n string = "" + string;\n let result = "";\n const firstcode = string.charCodeAt(0);\n for (let i = 0; i < string.length; i++) {\n const code = string.charCodeAt(i);\n if (code === 0)\n throw new InvalidCharacterError("Invalid character: the input contains U+0000.");\n if (between(code, 1, 31) || code === 127 || i === 0 && between(code, 48, 57) || i === 1 && between(code, 48, 57) && firstcode === 45)\n result += "\\\\" + code.toString(16) + " ";\n else if (code >= 128 || code === 45 || code === 95 || between(code, 48, 57) || between(code, 65, 90) || between(code, 97, 122))\n result += string[i];\n else\n result += "\\\\" + string[i];\n }\n return result;\n}\nfunction escapeHash(string) {\n string = "" + string;\n let result = "";\n for (let i = 0; i < string.length; i++) {\n const code = string.charCodeAt(i);\n if (code === 0)\n throw new InvalidCharacterError("Invalid character: the input contains U+0000.");\n if (code >= 128 || code === 45 || code === 95 || between(code, 48, 57) || between(code, 65, 90) || between(code, 97, 122))\n result += string[i];\n else\n result += "\\\\" + code.toString(16) + " ";\n }\n return result;\n}\nfunction escapeString(string) {\n string = "" + string;\n let result = "";\n for (let i = 0; i < string.length; i++) {\n const code = string.charCodeAt(i);\n if (code === 0)\n throw new InvalidCharacterError("Invalid character: the input contains U+0000.");\n if (between(code, 1, 31) || code === 127)\n result += "\\\\" + code.toString(16) + " ";\n else if (code === 34 || code === 92)\n result += "\\\\" + string[i];\n else\n result += string[i];\n }\n return result;\n}\n\n// packages/isomorphic/cssParser.ts\nvar InvalidSelectorError = class extends Error {\n};\nfunction parseCSS(selector, customNames) {\n let tokens;\n try {\n tokens = tokenize(selector);\n if (!(tokens[tokens.length - 1] instanceof EOFToken))\n tokens.push(new EOFToken());\n } catch (e) {\n const newMessage = e.message + ` while parsing css selector "${selector}". Did you mean to CSS.escape it?`;\n const index = (e.stack || "").indexOf(e.message);\n if (index !== -1)\n e.stack = e.stack.substring(0, index) + newMessage + e.stack.substring(index + e.message.length);\n e.message = newMessage;\n throw e;\n }\n const unsupportedToken = tokens.find((token) => {\n return token instanceof AtKeywordToken || token instanceof BadStringToken || token instanceof BadURLToken || token instanceof ColumnToken || token instanceof CDOToken || token instanceof CDCToken || token instanceof SemicolonToken || // TODO: Consider using these for something, e.g. to escape complex strings.\n // For example :xpath{ (//div/bar[@attr="foo"])[2]/baz }\n // Or this way :xpath( {complex-xpath-goes-here("hello")} )\n token instanceof OpenCurlyToken || token instanceof CloseCurlyToken || // TODO: Consider treating these as strings?\n token instanceof URLToken || token instanceof PercentageToken;\n });\n if (unsupportedToken)\n throw new InvalidSelectorError(`Unsupported token "${unsupportedToken.toSource()}" while parsing css selector "${selector}". Did you mean to CSS.escape it?`);\n let pos = 0;\n const names = /* @__PURE__ */ new Set();\n function unexpected() {\n return new InvalidSelectorError(`Unexpected token "${tokens[pos].toSource()}" while parsing css selector "${selector}". Did you mean to CSS.escape it?`);\n }\n function skipWhitespace() {\n while (tokens[pos] instanceof WhitespaceToken)\n pos++;\n }\n function isIdent(p = pos) {\n return tokens[p] instanceof IdentToken;\n }\n function isString(p = pos) {\n return tokens[p] instanceof StringToken;\n }\n function isNumber(p = pos) {\n return tokens[p] instanceof NumberToken;\n }\n function isComma(p = pos) {\n return tokens[p] instanceof CommaToken;\n }\n function isOpenParen(p = pos) {\n return tokens[p] instanceof OpenParenToken;\n }\n function isCloseParen(p = pos) {\n return tokens[p] instanceof CloseParenToken;\n }\n function isFunction(p = pos) {\n return tokens[p] instanceof FunctionToken;\n }\n function isStar(p = pos) {\n return tokens[p] instanceof DelimToken && tokens[p].value === "*";\n }\n function isEOF(p = pos) {\n return tokens[p] instanceof EOFToken;\n }\n function isClauseCombinator(p = pos) {\n return tokens[p] instanceof DelimToken && [">", "+", "~"].includes(tokens[p].value);\n }\n function isSelectorClauseEnd(p = pos) {\n return isComma(p) || isCloseParen(p) || isEOF(p) || isClauseCombinator(p) || tokens[p] instanceof WhitespaceToken;\n }\n function consumeFunctionArguments() {\n const result2 = [consumeArgument()];\n while (true) {\n skipWhitespace();\n if (!isComma())\n break;\n pos++;\n result2.push(consumeArgument());\n }\n return result2;\n }\n function consumeArgument() {\n skipWhitespace();\n if (isNumber())\n return tokens[pos++].value;\n if (isString())\n return tokens[pos++].value;\n return consumeComplexSelector();\n }\n function consumeComplexSelector() {\n const result2 = { simples: [] };\n skipWhitespace();\n if (isClauseCombinator()) {\n result2.simples.push({ selector: { functions: [{ name: "scope", args: [] }] }, combinator: "" });\n } else {\n result2.simples.push({ selector: consumeSimpleSelector(), combinator: "" });\n }\n while (true) {\n skipWhitespace();\n if (isClauseCombinator()) {\n result2.simples[result2.simples.length - 1].combinator = tokens[pos++].value;\n skipWhitespace();\n } else if (isSelectorClauseEnd()) {\n break;\n }\n result2.simples.push({ combinator: "", selector: consumeSimpleSelector() });\n }\n return result2;\n }\n function consumeSimpleSelector() {\n let rawCSSString = "";\n const functions = [];\n while (!isSelectorClauseEnd()) {\n if (isIdent() || isStar()) {\n rawCSSString += tokens[pos++].toSource();\n } else if (tokens[pos] instanceof HashToken) {\n rawCSSString += tokens[pos++].toSource();\n } else if (tokens[pos] instanceof DelimToken && tokens[pos].value === ".") {\n pos++;\n if (isIdent())\n rawCSSString += "." + tokens[pos++].toSource();\n else\n throw unexpected();\n } else if (tokens[pos] instanceof ColonToken) {\n pos++;\n if (isIdent()) {\n if (!customNames.has(tokens[pos].value.toLowerCase())) {\n rawCSSString += ":" + tokens[pos++].toSource();\n } else {\n const name = tokens[pos++].value.toLowerCase();\n functions.push({ name, args: [] });\n names.add(name);\n }\n } else if (isFunction()) {\n const name = tokens[pos++].value.toLowerCase();\n if (!customNames.has(name)) {\n rawCSSString += `:${name}(${consumeBuiltinFunctionArguments()})`;\n } else {\n functions.push({ name, args: consumeFunctionArguments() });\n names.add(name);\n }\n skipWhitespace();\n if (!isCloseParen())\n throw unexpected();\n pos++;\n } else {\n throw unexpected();\n }\n } else if (tokens[pos] instanceof OpenSquareToken) {\n rawCSSString += "[";\n pos++;\n while (!(tokens[pos] instanceof CloseSquareToken) && !isEOF())\n rawCSSString += tokens[pos++].toSource();\n if (!(tokens[pos] instanceof CloseSquareToken))\n throw unexpected();\n rawCSSString += "]";\n pos++;\n } else {\n throw unexpected();\n }\n }\n if (!rawCSSString && !functions.length)\n throw unexpected();\n return { css: rawCSSString || void 0, functions };\n }\n function consumeBuiltinFunctionArguments() {\n let s = "";\n let balance = 1;\n while (!isEOF()) {\n if (isOpenParen() || isFunction())\n balance++;\n if (isCloseParen())\n balance--;\n if (!balance)\n break;\n s += tokens[pos++].toSource();\n }\n return s;\n }\n const result = consumeFunctionArguments();\n if (!isEOF())\n throw unexpected();\n if (result.some((arg) => typeof arg !== "object" || !("simples" in arg)))\n throw new InvalidSelectorError(`Error while parsing css selector "${selector}". Did you mean to CSS.escape it?`);\n return { selector: result, names: Array.from(names) };\n}\n\n// packages/isomorphic/selectorParser.ts\nvar kNestedSelectorNames = /* @__PURE__ */ new Set(["internal:has", "internal:has-not", "internal:and", "internal:or", "internal:chain", "left-of", "right-of", "above", "below", "near"]);\nvar kNestedSelectorNamesWithDistance = /* @__PURE__ */ new Set(["left-of", "right-of", "above", "below", "near"]);\nvar customCSSNames = /* @__PURE__ */ new Set(["not", "is", "where", "has", "scope", "light", "visible", "text", "text-matches", "text-is", "has-text", "above", "below", "right-of", "left-of", "near", "nth-match"]);\nfunction parseSelector(selector) {\n const parsedStrings = parseSelectorString(selector);\n const parts = [];\n for (const part of parsedStrings.parts) {\n if (part.name === "css" || part.name === "css:light") {\n if (part.name === "css:light")\n part.body = ":light(" + part.body + ")";\n const parsedCSS = parseCSS(part.body, customCSSNames);\n parts.push({\n name: "css",\n body: parsedCSS.selector,\n source: part.body\n });\n continue;\n }\n if (kNestedSelectorNames.has(part.name)) {\n let innerSelector;\n let distance;\n try {\n const unescaped = JSON.parse("[" + part.body + "]");\n if (!Array.isArray(unescaped) || unescaped.length < 1 || unescaped.length > 2 || typeof unescaped[0] !== "string")\n throw new InvalidSelectorError(`Malformed selector: ${part.name}=` + part.body);\n innerSelector = unescaped[0];\n if (unescaped.length === 2) {\n if (typeof unescaped[1] !== "number" || !kNestedSelectorNamesWithDistance.has(part.name))\n throw new InvalidSelectorError(`Malformed selector: ${part.name}=` + part.body);\n distance = unescaped[1];\n }\n } catch (e) {\n throw new InvalidSelectorError(`Malformed selector: ${part.name}=` + part.body);\n }\n const nested = { name: part.name, source: part.body, body: { parsed: parseSelector(innerSelector), distance } };\n const lastFrame = [...nested.body.parsed.parts].reverse().find((part2) => part2.name === "internal:control" && part2.body === "enter-frame");\n const lastFrameIndex = lastFrame ? nested.body.parsed.parts.indexOf(lastFrame) : -1;\n if (lastFrameIndex !== -1 && selectorPartsEqual(nested.body.parsed.parts.slice(0, lastFrameIndex + 1), parts.slice(0, lastFrameIndex + 1)))\n nested.body.parsed.parts.splice(0, lastFrameIndex + 1);\n parts.push(nested);\n continue;\n }\n parts.push({ ...part, source: part.body });\n }\n if (kNestedSelectorNames.has(parts[0].name))\n throw new InvalidSelectorError(`"${parts[0].name}" selector cannot be first`);\n return {\n capture: parsedStrings.capture,\n parts\n };\n}\nfunction selectorPartsEqual(list1, list2) {\n return stringifySelector({ parts: list1 }) === stringifySelector({ parts: list2 });\n}\nfunction stringifySelector(selector, forceEngineName) {\n if (typeof selector === "string")\n return selector;\n return selector.parts.map((p, i) => {\n let includeEngine = true;\n if (!forceEngineName && i !== selector.capture) {\n if (p.name === "css")\n includeEngine = false;\n else if (p.name === "xpath" && p.source.startsWith("//") || p.source.startsWith(".."))\n includeEngine = false;\n }\n const prefix = includeEngine ? p.name + "=" : "";\n return `${i === selector.capture ? "*" : ""}${prefix}${p.source}`;\n }).join(" >> ");\n}\nfunction visitAllSelectorParts(selector, visitor) {\n const visit = (selector2, nested) => {\n for (const part of selector2.parts) {\n visitor(part, nested);\n if (kNestedSelectorNames.has(part.name))\n visit(part.body.parsed, true);\n }\n };\n visit(selector, false);\n}\nfunction parseSelectorString(selector) {\n let index = 0;\n let quote;\n let start = 0;\n const result = { parts: [] };\n const append = () => {\n const part = selector.substring(start, index).trim();\n const eqIndex = part.indexOf("=");\n let name;\n let body;\n if (eqIndex !== -1 && part.substring(0, eqIndex).trim().match(/^[a-zA-Z_0-9-+:*]+$/)) {\n name = part.substring(0, eqIndex).trim();\n body = part.substring(eqIndex + 1);\n } else if (part.length > 1 && part[0] === \'"\' && part[part.length - 1] === \'"\') {\n name = "text";\n body = part;\n } else if (part.length > 1 && part[0] === "\'" && part[part.length - 1] === "\'") {\n name = "text";\n body = part;\n } else if (/^\\(*\\/\\//.test(part) || part.startsWith("..")) {\n name = "xpath";\n body = part;\n } else {\n name = "css";\n body = part;\n }\n let capture = false;\n if (name[0] === "*") {\n capture = true;\n name = name.substring(1);\n }\n result.parts.push({ name, body });\n if (capture) {\n if (result.capture !== void 0)\n throw new InvalidSelectorError(`Only one of the selectors can capture using * modifier`);\n result.capture = result.parts.length - 1;\n }\n };\n if (!selector.includes(">>")) {\n index = selector.length;\n append();\n return result;\n }\n const shouldIgnoreTextSelectorQuote = () => {\n const prefix = selector.substring(start, index);\n const match = prefix.match(/^\\s*text\\s*=(.*)$/);\n return !!match && !!match[1];\n };\n while (index < selector.length) {\n const c = selector[index];\n if (c === "\\\\" && index + 1 < selector.length) {\n index += 2;\n } else if (c === quote) {\n quote = void 0;\n index++;\n } else if (!quote && (c === \'"\' || c === "\'" || c === "`") && !shouldIgnoreTextSelectorQuote()) {\n quote = c;\n index++;\n } else if (!quote && c === ">" && selector[index + 1] === ">") {\n append();\n index += 2;\n start = index;\n } else {\n index++;\n }\n }\n append();\n return result;\n}\nfunction parseAttributeSelector(selector, allowUnquotedStrings) {\n let wp = 0;\n let EOL = selector.length === 0;\n const next = () => selector[wp] || "";\n const eat1 = () => {\n const result2 = next();\n ++wp;\n EOL = wp >= selector.length;\n return result2;\n };\n const syntaxError = (stage) => {\n if (EOL)\n throw new InvalidSelectorError(`Unexpected end of selector while parsing selector \\`${selector}\\``);\n throw new InvalidSelectorError(`Error while parsing selector \\`${selector}\\` - unexpected symbol "${next()}" at position ${wp}` + (stage ? " during " + stage : ""));\n };\n function skipSpaces() {\n while (!EOL && /\\s/.test(next()))\n eat1();\n }\n function isCSSNameChar(char) {\n return char >= "\\x80" || char >= "0" && char <= "9" || char >= "A" && char <= "Z" || char >= "a" && char <= "z" || char >= "0" && char <= "9" || char === "_" || char === "-";\n }\n function readIdentifier() {\n let result2 = "";\n skipSpaces();\n while (!EOL && isCSSNameChar(next()))\n result2 += eat1();\n return result2;\n }\n function readQuotedString(quote) {\n let result2 = eat1();\n if (result2 !== quote)\n syntaxError("parsing quoted string");\n while (!EOL && next() !== quote) {\n if (next() === "\\\\")\n eat1();\n result2 += eat1();\n }\n if (next() !== quote)\n syntaxError("parsing quoted string");\n result2 += eat1();\n return result2;\n }\n function readRegularExpression() {\n if (eat1() !== "/")\n syntaxError("parsing regular expression");\n let source = "";\n let inClass = false;\n while (!EOL) {\n if (next() === "\\\\") {\n source += eat1();\n if (EOL)\n syntaxError("parsing regular expression");\n } else if (inClass && next() === "]") {\n inClass = false;\n } else if (!inClass && next() === "[") {\n inClass = true;\n } else if (!inClass && next() === "/") {\n break;\n }\n source += eat1();\n }\n if (eat1() !== "/")\n syntaxError("parsing regular expression");\n let flags = "";\n while (!EOL && next().match(/[dgimsuy]/))\n flags += eat1();\n try {\n return new RegExp(source, flags);\n } catch (e) {\n throw new InvalidSelectorError(`Error while parsing selector \\`${selector}\\`: ${e.message}`);\n }\n }\n function readAttributeToken() {\n let token = "";\n skipSpaces();\n if (next() === `\'` || next() === `"`)\n token = readQuotedString(next()).slice(1, -1);\n else\n token = readIdentifier();\n if (!token)\n syntaxError("parsing property path");\n return token;\n }\n function readOperator() {\n skipSpaces();\n let op = "";\n if (!EOL)\n op += eat1();\n if (!EOL && op !== "=")\n op += eat1();\n if (!["=", "*=", "^=", "$=", "|=", "~="].includes(op))\n syntaxError("parsing operator");\n return op;\n }\n function readAttribute() {\n eat1();\n const jsonPath = [];\n jsonPath.push(readAttributeToken());\n skipSpaces();\n while (next() === ".") {\n eat1();\n jsonPath.push(readAttributeToken());\n skipSpaces();\n }\n if (next() === "]") {\n eat1();\n return { name: jsonPath.join("."), jsonPath, op: "", value: null, caseSensitive: false };\n }\n const operator = readOperator();\n let value = void 0;\n let caseSensitive = true;\n skipSpaces();\n if (next() === "/") {\n if (operator !== "=")\n throw new InvalidSelectorError(`Error while parsing selector \\`${selector}\\` - cannot use ${operator} in attribute with regular expression`);\n value = readRegularExpression();\n } else if (next() === `\'` || next() === `"`) {\n value = readQuotedString(next()).slice(1, -1);\n skipSpaces();\n if (next() === "i" || next() === "I") {\n caseSensitive = false;\n eat1();\n } else if (next() === "s" || next() === "S") {\n caseSensitive = true;\n eat1();\n }\n } else {\n value = "";\n while (!EOL && (isCSSNameChar(next()) || next() === "+" || next() === "."))\n value += eat1();\n if (value === "true") {\n value = true;\n } else if (value === "false") {\n value = false;\n } else {\n if (!allowUnquotedStrings) {\n value = +value;\n if (Number.isNaN(value))\n syntaxError("parsing attribute value");\n }\n }\n }\n skipSpaces();\n if (next() !== "]")\n syntaxError("parsing attribute value");\n eat1();\n if (operator !== "=" && typeof value !== "string")\n throw new InvalidSelectorError(`Error while parsing selector \\`${selector}\\` - cannot use ${operator} in attribute with non-string matching value - ${value}`);\n return { name: jsonPath.join("."), jsonPath, op: operator, value, caseSensitive };\n }\n const result = {\n name: "",\n attributes: []\n };\n result.name = readIdentifier();\n skipSpaces();\n while (next() === "[") {\n result.attributes.push(readAttribute());\n skipSpaces();\n }\n if (!EOL)\n syntaxError(void 0);\n if (!result.name && !result.attributes.length)\n throw new InvalidSelectorError(`Error while parsing selector \\`${selector}\\` - selector cannot be empty`);\n return result;\n}\n\n// packages/isomorphic/stringUtils.ts\nfunction escapeWithQuotes(text, char = "\'") {\n const stringified = JSON.stringify(text);\n const escapedText = stringified.substring(1, stringified.length - 1).replace(/\\\\"/g, \'"\');\n if (char === "\'")\n return char + escapedText.replace(/[\']/g, "\\\\\'") + char;\n if (char === \'"\')\n return char + escapedText.replace(/["]/g, \'\\\\"\') + char;\n if (char === "`")\n return char + escapedText.replace(/[`]/g, "\\\\`") + char;\n throw new Error("Invalid escape char");\n}\nfunction toTitleCase(name) {\n return name.charAt(0).toUpperCase() + name.substring(1);\n}\nfunction toSnakeCase(name) {\n return name.replace(/([a-z0-9])([A-Z])/g, "$1_$2").replace(/([A-Z])([A-Z][a-z])/g, "$1_$2").toLowerCase();\n}\nfunction quoteCSSAttributeValue(text) {\n return `"${text.replace(/["\\\\]/g, (char) => "\\\\" + char)}"`;\n}\nvar normalizedWhitespaceCache;\nfunction cacheNormalizedWhitespaces() {\n normalizedWhitespaceCache = /* @__PURE__ */ new Map();\n}\nfunction normalizeWhiteSpace(text) {\n let result = normalizedWhitespaceCache == null ? void 0 : normalizedWhitespaceCache.get(text);\n if (result === void 0) {\n result = text.replace(/[\\u200b\\u00ad]/g, "").trim().replace(/\\s+/g, " ");\n normalizedWhitespaceCache == null ? void 0 : normalizedWhitespaceCache.set(text, result);\n }\n return result;\n}\nfunction normalizeEscapedRegexQuotes(source) {\n return source.replace(/(^|[^\\\\])(\\\\\\\\)*\\\\([\'"`])/g, "$1$2$3");\n}\nfunction escapeRegexForSelector(re) {\n if (re.unicode || re.unicodeSets)\n return String(re);\n return String(re).replace(/(^|[^\\\\])(\\\\\\\\)*(["\'`])/g, "$1$2\\\\$3").replace(/>>/g, "\\\\>\\\\>");\n}\nfunction escapeForTextSelector(text, exact) {\n if (typeof text !== "string")\n return escapeRegexForSelector(text);\n return `${JSON.stringify(text)}${exact ? "s" : "i"}`;\n}\nfunction escapeForAttributeSelector(value, exact) {\n if (typeof value !== "string")\n return escapeRegexForSelector(value);\n return `"${value.replace(/\\\\/g, "\\\\\\\\").replace(/["]/g, \'\\\\"\')}"${exact ? "s" : "i"}`;\n}\nfunction trimString(input, cap, suffix = "") {\n if (input.length <= cap)\n return input;\n const chars = [...input];\n if (chars.length > cap)\n return chars.slice(0, cap - suffix.length).join("") + suffix;\n return chars.join("");\n}\nfunction trimStringWithEllipsis(input, cap) {\n return trimString(input, cap, "\\u2026");\n}\nfunction escapeRegExp(s) {\n return s.replace(/[.*+?^${}()|[\\]\\\\]/g, "\\\\$&");\n}\nfunction longestCommonSubstring(s1, s2) {\n const n = s1.length;\n const m = s2.length;\n let maxLen = 0;\n let endingIndex = 0;\n const dp = Array(n + 1).fill(null).map(() => Array(m + 1).fill(0));\n for (let i = 1; i <= n; i++) {\n for (let j = 1; j <= m; j++) {\n if (s1[i - 1] === s2[j - 1]) {\n dp[i][j] = dp[i - 1][j - 1] + 1;\n if (dp[i][j] > maxLen) {\n maxLen = dp[i][j];\n endingIndex = i;\n }\n }\n }\n }\n return s1.slice(endingIndex - maxLen, endingIndex);\n}\nvar ansiRegex = new RegExp("([\\\\u001B\\\\u009B][[\\\\]()#?]*(?:(?:(?:[a-zA-Z\\\\d]*(?:;[-a-zA-Z\\\\d\\\\/#&.:=?%@~_]*)*)?\\\\u0007)|(?:(?:\\\\d{0,4}(?:;\\\\d{0,4})*)?[\\\\dA-PR-TZcf-ntqry=><~])))", "g");\n\n// packages/isomorphic/locatorGenerators.ts\nfunction asLocator(lang, selector, isFrameLocator = false) {\n return asLocators(lang, selector, isFrameLocator, 1)[0];\n}\nfunction asLocators(lang, selector, isFrameLocator = false, maxOutputSize = 20, preferredQuote) {\n try {\n return innerAsLocators(new generators[lang](preferredQuote), parseSelector(selector), isFrameLocator, maxOutputSize);\n } catch (e) {\n return [selector];\n }\n}\nfunction innerAsLocators(factory, parsed, isFrameLocator = false, maxOutputSize = 20) {\n const parts = [...parsed.parts];\n const tokens = [];\n let nextBase = isFrameLocator ? "frame-locator" : "page";\n for (let index = 0; index < parts.length; index++) {\n const part = parts[index];\n const base = nextBase;\n nextBase = "locator";\n if (part.name === "internal:describe")\n continue;\n if (part.name === "nth") {\n if (part.body === "0")\n tokens.push([factory.generateLocator(base, "first", ""), factory.generateLocator(base, "nth", "0")]);\n else if (part.body === "-1")\n tokens.push([factory.generateLocator(base, "last", ""), factory.generateLocator(base, "nth", "-1")]);\n else\n tokens.push([factory.generateLocator(base, "nth", part.body)]);\n continue;\n }\n if (part.name === "visible") {\n tokens.push([factory.generateLocator(base, "visible", part.body), factory.generateLocator(base, "default", `visible=${part.body}`)]);\n continue;\n }\n if (part.name === "internal:text") {\n const { exact, text } = detectExact(part.body);\n tokens.push([factory.generateLocator(base, "text", text, { exact })]);\n continue;\n }\n if (part.name === "internal:has-text") {\n const { exact, text } = detectExact(part.body);\n if (!exact) {\n tokens.push([factory.generateLocator(base, "has-text", text, { exact })]);\n continue;\n }\n }\n if (part.name === "internal:has-not-text") {\n const { exact, text } = detectExact(part.body);\n if (!exact) {\n tokens.push([factory.generateLocator(base, "has-not-text", text, { exact })]);\n continue;\n }\n }\n if (part.name === "internal:has") {\n const inners = innerAsLocators(factory, part.body.parsed, false, maxOutputSize);\n tokens.push(inners.map((inner) => factory.generateLocator(base, "has", inner)));\n continue;\n }\n if (part.name === "internal:has-not") {\n const inners = innerAsLocators(factory, part.body.parsed, false, maxOutputSize);\n tokens.push(inners.map((inner) => factory.generateLocator(base, "hasNot", inner)));\n continue;\n }\n if (part.name === "internal:and") {\n const inners = innerAsLocators(factory, part.body.parsed, false, maxOutputSize);\n tokens.push(inners.map((inner) => factory.generateLocator(base, "and", inner)));\n continue;\n }\n if (part.name === "internal:or") {\n const inners = innerAsLocators(factory, part.body.parsed, false, maxOutputSize);\n tokens.push(inners.map((inner) => factory.generateLocator(base, "or", inner)));\n continue;\n }\n if (part.name === "internal:chain") {\n const inners = innerAsLocators(factory, part.body.parsed, false, maxOutputSize);\n tokens.push(inners.map((inner) => factory.generateLocator(base, "chain", inner)));\n continue;\n }\n if (part.name === "internal:label") {\n const { exact, text } = detectExact(part.body);\n tokens.push([factory.generateLocator(base, "label", text, { exact })]);\n continue;\n }\n if (part.name === "internal:role") {\n const attrSelector = parseAttributeSelector(part.body, true);\n const options = { attrs: [] };\n for (const attr of attrSelector.attributes) {\n if (attr.name === "name") {\n if (options.exact !== void 0 && options.exact !== attr.caseSensitive)\n throw new Error(`Conflicting exactness in internal:role selector: ${stringifySelector({ parts: [part] })}`);\n options.exact = attr.caseSensitive;\n options.name = attr.value;\n } else if (attr.name === "description") {\n if (options.exact !== void 0 && options.exact !== attr.caseSensitive)\n throw new Error(`Conflicting exactness in internal:role selector: ${stringifySelector({ parts: [part] })}`);\n options.exact = attr.caseSensitive;\n options.description = attr.value;\n } else {\n if (attr.name === "level" && typeof attr.value === "string")\n attr.value = +attr.value;\n options.attrs.push({ name: attr.name === "include-hidden" ? "includeHidden" : attr.name, value: attr.value });\n }\n }\n tokens.push([factory.generateLocator(base, "role", attrSelector.name, options)]);\n continue;\n }\n if (part.name === "internal:testid") {\n const attrSelector = parseAttributeSelector(part.body, true);\n const { value } = attrSelector.attributes[0];\n tokens.push([factory.generateLocator(base, "test-id", value)]);\n continue;\n }\n if (part.name === "internal:attr") {\n const attrSelector = parseAttributeSelector(part.body, true);\n const { name, value, caseSensitive } = attrSelector.attributes[0];\n const text = value;\n const exact = !!caseSensitive;\n if (name === "placeholder") {\n tokens.push([factory.generateLocator(base, "placeholder", text, { exact })]);\n continue;\n }\n if (name === "alt") {\n tokens.push([factory.generateLocator(base, "alt", text, { exact })]);\n continue;\n }\n if (name === "title") {\n tokens.push([factory.generateLocator(base, "title", text, { exact })]);\n continue;\n }\n }\n if (part.name === "internal:control" && part.body === "enter-frame") {\n const lastTokens = tokens[tokens.length - 1];\n const lastPart = parts[index - 1];\n const transformed = lastTokens.map((token) => factory.chainLocators([token, factory.generateLocator(base, "frame", "")]));\n if (["xpath", "css"].includes(lastPart.name)) {\n transformed.push(\n factory.generateLocator(base, "frame-locator", stringifySelector({ parts: [lastPart] })),\n factory.generateLocator(base, "frame-locator", stringifySelector({ parts: [lastPart] }, true))\n );\n }\n lastTokens.splice(0, lastTokens.length, ...transformed);\n nextBase = "frame-locator";\n continue;\n }\n const nextPart = parts[index + 1];\n const selectorPart = stringifySelector({ parts: [part] });\n const locatorPart = factory.generateLocator(base, "default", selectorPart);\n if (nextPart && ["internal:has-text", "internal:has-not-text"].includes(nextPart.name)) {\n const { exact, text } = detectExact(nextPart.body);\n if (!exact) {\n const nextLocatorPart = factory.generateLocator("locator", nextPart.name === "internal:has-text" ? "has-text" : "has-not-text", text, { exact });\n const options = {};\n if (nextPart.name === "internal:has-text")\n options.hasText = text;\n else\n options.hasNotText = text;\n const combinedPart = factory.generateLocator(base, "default", selectorPart, options);\n tokens.push([factory.chainLocators([locatorPart, nextLocatorPart]), combinedPart]);\n index++;\n continue;\n }\n }\n let locatorPartWithEngine;\n if (["xpath", "css"].includes(part.name)) {\n const selectorPart2 = stringifySelector(\n { parts: [part] },\n /* forceEngineName */\n true\n );\n locatorPartWithEngine = factory.generateLocator(base, "default", selectorPart2);\n }\n tokens.push([locatorPart, locatorPartWithEngine].filter(Boolean));\n }\n return combineTokens(factory, tokens, maxOutputSize);\n}\nfunction combineTokens(factory, tokens, maxOutputSize) {\n const currentTokens = tokens.map(() => "");\n const result = [];\n const visit = (index) => {\n if (index === tokens.length) {\n result.push(factory.chainLocators(currentTokens));\n return result.length < maxOutputSize;\n }\n for (const taken of tokens[index]) {\n currentTokens[index] = taken;\n if (!visit(index + 1))\n return false;\n }\n return true;\n };\n visit(0);\n return result;\n}\nfunction detectExact(text) {\n let exact = false;\n const match = text.match(/^\\/(.*)\\/([igm]*)$/);\n if (match)\n return { text: new RegExp(match[1], match[2]) };\n if (text.endsWith(\'"\')) {\n text = JSON.parse(text);\n exact = true;\n } else if (text.endsWith(\'"s\')) {\n text = JSON.parse(text.substring(0, text.length - 1));\n exact = true;\n } else if (text.endsWith(\'"i\')) {\n text = JSON.parse(text.substring(0, text.length - 1));\n exact = false;\n }\n return { exact, text };\n}\nvar JavaScriptLocatorFactory = class {\n constructor(preferredQuote) {\n this.preferredQuote = preferredQuote;\n }\n generateLocator(base, kind, body, options = {}) {\n switch (kind) {\n case "default":\n if (options.hasText !== void 0)\n return `locator(${this.quote(body)}, { hasText: ${this.toHasText(options.hasText)} })`;\n if (options.hasNotText !== void 0)\n return `locator(${this.quote(body)}, { hasNotText: ${this.toHasText(options.hasNotText)} })`;\n return `locator(${this.quote(body)})`;\n case "frame-locator":\n return `frameLocator(${this.quote(body)})`;\n case "frame":\n return `contentFrame()`;\n case "nth":\n return `nth(${body})`;\n case "first":\n return `first()`;\n case "last":\n return `last()`;\n case "visible":\n return `filter({ visible: ${body === "true" ? "true" : "false"} })`;\n case "role":\n const attrs = [];\n if (isRegExp(options.name))\n attrs.push(`name: ${this.regexToSourceString(options.name)}`);\n else if (typeof options.name === "string")\n attrs.push(`name: ${this.quote(options.name)}`);\n if (isRegExp(options.description))\n attrs.push(`description: ${this.regexToSourceString(options.description)}`);\n else if (typeof options.description === "string")\n attrs.push(`description: ${this.quote(options.description)}`);\n if (options.exact && (typeof options.name === "string" || typeof options.description === "string"))\n attrs.push(`exact: true`);\n for (const { name, value } of options.attrs)\n attrs.push(`${name}: ${typeof value === "string" ? this.quote(value) : value}`);\n const attrString = attrs.length ? `, { ${attrs.join(", ")} }` : "";\n return `getByRole(${this.quote(body)}${attrString})`;\n case "has-text":\n return `filter({ hasText: ${this.toHasText(body)} })`;\n case "has-not-text":\n return `filter({ hasNotText: ${this.toHasText(body)} })`;\n case "has":\n return `filter({ has: ${body} })`;\n case "hasNot":\n return `filter({ hasNot: ${body} })`;\n case "and":\n return `and(${body})`;\n case "or":\n return `or(${body})`;\n case "chain":\n return `locator(${body})`;\n case "test-id":\n return `getByTestId(${this.toTestIdValue(body)})`;\n case "text":\n return this.toCallWithExact("getByText", body, !!options.exact);\n case "alt":\n return this.toCallWithExact("getByAltText", body, !!options.exact);\n case "placeholder":\n return this.toCallWithExact("getByPlaceholder", body, !!options.exact);\n case "label":\n return this.toCallWithExact("getByLabel", body, !!options.exact);\n case "title":\n return this.toCallWithExact("getByTitle", body, !!options.exact);\n default:\n throw new Error("Unknown selector kind " + kind);\n }\n }\n chainLocators(locators) {\n return locators.join(".");\n }\n regexToSourceString(re) {\n return normalizeEscapedRegexQuotes(String(re));\n }\n toCallWithExact(method, body, exact) {\n if (isRegExp(body))\n return `${method}(${this.regexToSourceString(body)})`;\n return exact ? `${method}(${this.quote(body)}, { exact: true })` : `${method}(${this.quote(body)})`;\n }\n toHasText(body) {\n if (isRegExp(body))\n return this.regexToSourceString(body);\n return this.quote(body);\n }\n toTestIdValue(value) {\n if (isRegExp(value))\n return this.regexToSourceString(value);\n return this.quote(value);\n }\n quote(text) {\n var _a;\n return escapeWithQuotes(text, (_a = this.preferredQuote) != null ? _a : "\'");\n }\n};\nvar PythonLocatorFactory = class {\n generateLocator(base, kind, body, options = {}) {\n switch (kind) {\n case "default":\n if (options.hasText !== void 0)\n return `locator(${this.quote(body)}, has_text=${this.toHasText(options.hasText)})`;\n if (options.hasNotText !== void 0)\n return `locator(${this.quote(body)}, has_not_text=${this.toHasText(options.hasNotText)})`;\n return `locator(${this.quote(body)})`;\n case "frame-locator":\n return `frame_locator(${this.quote(body)})`;\n case "frame":\n return `content_frame`;\n case "nth":\n return `nth(${body})`;\n case "first":\n return `first`;\n case "last":\n return `last`;\n case "visible":\n return `filter(visible=${body === "true" ? "True" : "False"})`;\n case "role":\n const attrs = [];\n if (isRegExp(options.name))\n attrs.push(`name=${this.regexToString(options.name)}`);\n else if (typeof options.name === "string")\n attrs.push(`name=${this.quote(options.name)}`);\n if (isRegExp(options.description))\n attrs.push(`description=${this.regexToString(options.description)}`);\n else if (typeof options.description === "string")\n attrs.push(`description=${this.quote(options.description)}`);\n if (options.exact && (typeof options.name === "string" || typeof options.description === "string"))\n attrs.push(`exact=True`);\n for (const { name, value } of options.attrs) {\n let valueString = typeof value === "string" ? this.quote(value) : value;\n if (typeof value === "boolean")\n valueString = value ? "True" : "False";\n attrs.push(`${toSnakeCase(name)}=${valueString}`);\n }\n const attrString = attrs.length ? `, ${attrs.join(", ")}` : "";\n return `get_by_role(${this.quote(body)}${attrString})`;\n case "has-text":\n return `filter(has_text=${this.toHasText(body)})`;\n case "has-not-text":\n return `filter(has_not_text=${this.toHasText(body)})`;\n case "has":\n return `filter(has=${body})`;\n case "hasNot":\n return `filter(has_not=${body})`;\n case "and":\n return `and_(${body})`;\n case "or":\n return `or_(${body})`;\n case "chain":\n return `locator(${body})`;\n case "test-id":\n return `get_by_test_id(${this.toTestIdValue(body)})`;\n case "text":\n return this.toCallWithExact("get_by_text", body, !!options.exact);\n case "alt":\n return this.toCallWithExact("get_by_alt_text", body, !!options.exact);\n case "placeholder":\n return this.toCallWithExact("get_by_placeholder", body, !!options.exact);\n case "label":\n return this.toCallWithExact("get_by_label", body, !!options.exact);\n case "title":\n return this.toCallWithExact("get_by_title", body, !!options.exact);\n default:\n throw new Error("Unknown selector kind " + kind);\n }\n }\n chainLocators(locators) {\n return locators.join(".");\n }\n regexToString(body) {\n const suffix = body.flags.includes("i") ? ", re.IGNORECASE" : "";\n return `re.compile(r"${normalizeEscapedRegexQuotes(body.source).replace(/\\\\\\//, "/").replace(/"/g, \'\\\\"\')}"${suffix})`;\n }\n toCallWithExact(method, body, exact) {\n if (isRegExp(body))\n return `${method}(${this.regexToString(body)})`;\n if (exact)\n return `${method}(${this.quote(body)}, exact=True)`;\n return `${method}(${this.quote(body)})`;\n }\n toHasText(body) {\n if (isRegExp(body))\n return this.regexToString(body);\n return `${this.quote(body)}`;\n }\n toTestIdValue(value) {\n if (isRegExp(value))\n return this.regexToString(value);\n return this.quote(value);\n }\n quote(text) {\n return escapeWithQuotes(text, \'"\');\n }\n};\nvar JavaLocatorFactory = class {\n generateLocator(base, kind, body, options = {}) {\n let clazz;\n switch (base) {\n case "page":\n clazz = "Page";\n break;\n case "frame-locator":\n clazz = "FrameLocator";\n break;\n case "locator":\n clazz = "Locator";\n break;\n }\n switch (kind) {\n case "default":\n if (options.hasText !== void 0)\n return `locator(${this.quote(body)}, new ${clazz}.LocatorOptions().setHasText(${this.toHasText(options.hasText)}))`;\n if (options.hasNotText !== void 0)\n return `locator(${this.quote(body)}, new ${clazz}.LocatorOptions().setHasNotText(${this.toHasText(options.hasNotText)}))`;\n return `locator(${this.quote(body)})`;\n case "frame-locator":\n return `frameLocator(${this.quote(body)})`;\n case "frame":\n return `contentFrame()`;\n case "nth":\n return `nth(${body})`;\n case "first":\n return `first()`;\n case "last":\n return `last()`;\n case "visible":\n return `filter(new ${clazz}.FilterOptions().setVisible(${body === "true" ? "true" : "false"}))`;\n case "role":\n const attrs = [];\n if (isRegExp(options.name))\n attrs.push(`.setName(${this.regexToString(options.name)})`);\n else if (typeof options.name === "string")\n attrs.push(`.setName(${this.quote(options.name)})`);\n if (isRegExp(options.description))\n attrs.push(`.setDescription(${this.regexToString(options.description)})`);\n else if (typeof options.description === "string")\n attrs.push(`.setDescription(${this.quote(options.description)})`);\n if (options.exact && (typeof options.name === "string" || typeof options.description === "string"))\n attrs.push(`.setExact(true)`);\n for (const { name, value } of options.attrs)\n attrs.push(`.set${toTitleCase(name)}(${typeof value === "string" ? this.quote(value) : value})`);\n const attrString = attrs.length ? `, new ${clazz}.GetByRoleOptions()${attrs.join("")}` : "";\n return `getByRole(AriaRole.${toSnakeCase(body).toUpperCase()}${attrString})`;\n case "has-text":\n return `filter(new ${clazz}.FilterOptions().setHasText(${this.toHasText(body)}))`;\n case "has-not-text":\n return `filter(new ${clazz}.FilterOptions().setHasNotText(${this.toHasText(body)}))`;\n case "has":\n return `filter(new ${clazz}.FilterOptions().setHas(${body}))`;\n case "hasNot":\n return `filter(new ${clazz}.FilterOptions().setHasNot(${body}))`;\n case "and":\n return `and(${body})`;\n case "or":\n return `or(${body})`;\n case "chain":\n return `locator(${body})`;\n case "test-id":\n return `getByTestId(${this.toTestIdValue(body)})`;\n case "text":\n return this.toCallWithExact(clazz, "getByText", body, !!options.exact);\n case "alt":\n return this.toCallWithExact(clazz, "getByAltText", body, !!options.exact);\n case "placeholder":\n return this.toCallWithExact(clazz, "getByPlaceholder", body, !!options.exact);\n case "label":\n return this.toCallWithExact(clazz, "getByLabel", body, !!options.exact);\n case "title":\n return this.toCallWithExact(clazz, "getByTitle", body, !!options.exact);\n default:\n throw new Error("Unknown selector kind " + kind);\n }\n }\n chainLocators(locators) {\n return locators.join(".");\n }\n regexToString(body) {\n const suffix = body.flags.includes("i") ? ", Pattern.CASE_INSENSITIVE" : "";\n return `Pattern.compile(${this.quote(normalizeEscapedRegexQuotes(body.source))}${suffix})`;\n }\n toCallWithExact(clazz, method, body, exact) {\n if (isRegExp(body))\n return `${method}(${this.regexToString(body)})`;\n if (exact)\n return `${method}(${this.quote(body)}, new ${clazz}.${toTitleCase(method)}Options().setExact(true))`;\n return `${method}(${this.quote(body)})`;\n }\n toHasText(body) {\n if (isRegExp(body))\n return this.regexToString(body);\n return this.quote(body);\n }\n toTestIdValue(value) {\n if (isRegExp(value))\n return this.regexToString(value);\n return this.quote(value);\n }\n quote(text) {\n return escapeWithQuotes(text, \'"\');\n }\n};\nvar CSharpLocatorFactory = class {\n generateLocator(base, kind, body, options = {}) {\n switch (kind) {\n case "default":\n if (options.hasText !== void 0)\n return `Locator(${this.quote(body)}, new() { ${this.toHasText(options.hasText)} })`;\n if (options.hasNotText !== void 0)\n return `Locator(${this.quote(body)}, new() { ${this.toHasNotText(options.hasNotText)} })`;\n return `Locator(${this.quote(body)})`;\n case "frame-locator":\n return `FrameLocator(${this.quote(body)})`;\n case "frame":\n return `ContentFrame`;\n case "nth":\n return `Nth(${body})`;\n case "first":\n return `First`;\n case "last":\n return `Last`;\n case "visible":\n return `Filter(new() { Visible = ${body === "true" ? "true" : "false"} })`;\n case "role":\n const attrs = [];\n if (isRegExp(options.name))\n attrs.push(`NameRegex = ${this.regexToString(options.name)}`);\n else if (typeof options.name === "string")\n attrs.push(`Name = ${this.quote(options.name)}`);\n if (isRegExp(options.description))\n attrs.push(`DescriptionRegex = ${this.regexToString(options.description)}`);\n else if (typeof options.description === "string")\n attrs.push(`Description = ${this.quote(options.description)}`);\n if (options.exact && (typeof options.name === "string" || typeof options.description === "string"))\n attrs.push(`Exact = true`);\n for (const { name, value } of options.attrs)\n attrs.push(`${toTitleCase(name)} = ${typeof value === "string" ? this.quote(value) : value}`);\n const attrString = attrs.length ? `, new() { ${attrs.join(", ")} }` : "";\n return `GetByRole(AriaRole.${toTitleCase(body)}${attrString})`;\n case "has-text":\n return `Filter(new() { ${this.toHasText(body)} })`;\n case "has-not-text":\n return `Filter(new() { ${this.toHasNotText(body)} })`;\n case "has":\n return `Filter(new() { Has = ${body} })`;\n case "hasNot":\n return `Filter(new() { HasNot = ${body} })`;\n case "and":\n return `And(${body})`;\n case "or":\n return `Or(${body})`;\n case "chain":\n return `Locator(${body})`;\n case "test-id":\n return `GetByTestId(${this.toTestIdValue(body)})`;\n case "text":\n return this.toCallWithExact("GetByText", body, !!options.exact);\n case "alt":\n return this.toCallWithExact("GetByAltText", body, !!options.exact);\n case "placeholder":\n return this.toCallWithExact("GetByPlaceholder", body, !!options.exact);\n case "label":\n return this.toCallWithExact("GetByLabel", body, !!options.exact);\n case "title":\n return this.toCallWithExact("GetByTitle", body, !!options.exact);\n default:\n throw new Error("Unknown selector kind " + kind);\n }\n }\n chainLocators(locators) {\n return locators.join(".");\n }\n regexToString(body) {\n const suffix = body.flags.includes("i") ? ", RegexOptions.IgnoreCase" : "";\n return `new Regex(${this.quote(normalizeEscapedRegexQuotes(body.source))}${suffix})`;\n }\n toCallWithExact(method, body, exact) {\n if (isRegExp(body))\n return `${method}(${this.regexToString(body)})`;\n if (exact)\n return `${method}(${this.quote(body)}, new() { Exact = true })`;\n return `${method}(${this.quote(body)})`;\n }\n toHasText(body) {\n if (isRegExp(body))\n return `HasTextRegex = ${this.regexToString(body)}`;\n return `HasText = ${this.quote(body)}`;\n }\n toTestIdValue(value) {\n if (isRegExp(value))\n return this.regexToString(value);\n return this.quote(value);\n }\n toHasNotText(body) {\n if (isRegExp(body))\n return `HasNotTextRegex = ${this.regexToString(body)}`;\n return `HasNotText = ${this.quote(body)}`;\n }\n quote(text) {\n return escapeWithQuotes(text, \'"\');\n }\n};\nvar JsonlLocatorFactory = class {\n generateLocator(base, kind, body, options = {}) {\n return JSON.stringify({\n kind,\n body,\n options\n });\n }\n chainLocators(locators) {\n const objects = locators.map((l) => JSON.parse(l));\n for (let i = 0; i < objects.length - 1; ++i)\n objects[i].next = objects[i + 1];\n return JSON.stringify(objects[0]);\n }\n};\nvar generators = {\n javascript: JavaScriptLocatorFactory,\n python: PythonLocatorFactory,\n java: JavaLocatorFactory,\n csharp: CSharpLocatorFactory,\n jsonl: JsonlLocatorFactory\n};\nfunction isRegExp(obj) {\n return obj instanceof RegExp;\n}\n\n// packages/isomorphic/locatorUtils.ts\nfunction getByAttributeTextSelector(attrName, text, options) {\n return `internal:attr=[${attrName}=${escapeForAttributeSelector(text, (options == null ? void 0 : options.exact) || false)}]`;\n}\nfunction splitTestIdAttributeNames(testIdAttributeName) {\n return testIdAttributeName.split(",");\n}\nfunction encodeTestIdAttributeName(testIdAttributeName) {\n return testIdAttributeName.includes(",") ? JSON.stringify(testIdAttributeName) : testIdAttributeName;\n}\nfunction getByTestIdSelector(testIdAttributeName, testId) {\n return `internal:testid=[${encodeTestIdAttributeName(testIdAttributeName)}=${escapeForAttributeSelector(testId, true)}]`;\n}\nfunction getByLabelSelector(text, options) {\n return "internal:label=" + escapeForTextSelector(text, !!(options == null ? void 0 : options.exact));\n}\nfunction getByAltTextSelector(text, options) {\n return getByAttributeTextSelector("alt", text, options);\n}\nfunction getByTitleSelector(text, options) {\n return getByAttributeTextSelector("title", text, options);\n}\nfunction getByPlaceholderSelector(text, options) {\n return getByAttributeTextSelector("placeholder", text, options);\n}\nfunction getByTextSelector(text, options) {\n return "internal:text=" + escapeForTextSelector(text, !!(options == null ? void 0 : options.exact));\n}\nfunction getByRoleSelector(role, options = {}) {\n const props = [];\n if (options.checked !== void 0)\n props.push(["checked", String(options.checked)]);\n if (options.disabled !== void 0)\n props.push(["disabled", String(options.disabled)]);\n if (options.selected !== void 0)\n props.push(["selected", String(options.selected)]);\n if (options.expanded !== void 0)\n props.push(["expanded", String(options.expanded)]);\n if (options.includeHidden !== void 0)\n props.push(["include-hidden", String(options.includeHidden)]);\n if (options.level !== void 0)\n props.push(["level", String(options.level)]);\n if (options.name !== void 0)\n props.push(["name", escapeForAttributeSelector(options.name, !!options.exact)]);\n if (options.description !== void 0)\n props.push(["description", escapeForAttributeSelector(options.description, !!options.exact)]);\n if (options.pressed !== void 0)\n props.push(["pressed", String(options.pressed)]);\n return `internal:role=${role}${props.map(([n, v]) => `[${n}=${v}]`).join("")}`;\n}\n\n// packages/isomorphic/yaml.ts\nfunction yamlEscapeKeyIfNeeded(str) {\n if (!yamlStringNeedsQuotes(str))\n return str;\n return `\'` + str.replace(/\'/g, `\'\'`) + `\'`;\n}\nfunction yamlEscapeValueIfNeeded(str) {\n if (!yamlStringNeedsQuotes(str))\n return str;\n return \'"\' + str.replace(/[\\\\"\\x00-\\x1f\\x7f-\\x9f]/g, (c) => {\n switch (c) {\n case "\\\\":\n return "\\\\\\\\";\n case \'"\':\n return \'\\\\"\';\n case "\\b":\n return "\\\\b";\n case "\\f":\n return "\\\\f";\n case "\\n":\n return "\\\\n";\n case "\\r":\n return "\\\\r";\n case " ":\n return "\\\\t";\n default:\n const code = c.charCodeAt(0);\n return "\\\\x" + code.toString(16).padStart(2, "0");\n }\n }) + \'"\';\n}\nfunction yamlStringNeedsQuotes(str) {\n if (str.length === 0)\n return true;\n if (/^\\s|\\s$/.test(str))\n return true;\n if (/[\\x00-\\x08\\x0b\\x0c\\x0e-\\x1f\\x7f-\\x9f]/.test(str))\n return true;\n if (/^-/.test(str))\n return true;\n if (/[\\n:](\\s|$)/.test(str))\n return true;\n if (/\\s#/.test(str))\n return true;\n if (/[\\n\\r]/.test(str))\n return true;\n if (/^[&*\\],?!>|@"\'#%]/.test(str))\n return true;\n if (/[{}`]/.test(str))\n return true;\n if (/^\\[/.test(str))\n return true;\n if (!isNaN(Number(str)) || ["y", "n", "yes", "no", "true", "false", "on", "off", "null"].includes(str.toLowerCase()))\n return true;\n return false;\n}\n\n// packages/injected/src/domUtils.ts\nvar globalOptions = {};\nfunction setGlobalOptions(options) {\n globalOptions = options;\n}\nfunction isInsideScope(scope, element) {\n while (element) {\n if (scope.contains(element))\n return true;\n element = enclosingShadowHost(element);\n }\n return false;\n}\nfunction parentElementOrShadowHost(element) {\n if (element.parentElement)\n return element.parentElement;\n if (!element.parentNode)\n return;\n if (element.parentNode.nodeType === 11 && element.parentNode.host)\n return element.parentNode.host;\n}\nfunction enclosingShadowRootOrDocument(element) {\n let node = element;\n while (node.parentNode)\n node = node.parentNode;\n if (node.nodeType === 11 || node.nodeType === 9)\n return node;\n}\nfunction enclosingShadowHost(element) {\n while (element.parentElement)\n element = element.parentElement;\n return parentElementOrShadowHost(element);\n}\nfunction closestCrossShadow(element, css, scope) {\n while (element) {\n const closest = element.closest(css);\n if (scope && closest !== scope && (closest == null ? void 0 : closest.contains(scope)))\n return;\n if (closest)\n return closest;\n element = enclosingShadowHost(element);\n }\n}\nfunction getElementComputedStyle(element, pseudo) {\n const cache = pseudo === "::before" ? cacheStyleBefore : pseudo === "::after" ? cacheStyleAfter : cacheStyle;\n if (cache && cache.has(element))\n return cache.get(element);\n const style = element.ownerDocument && element.ownerDocument.defaultView ? element.ownerDocument.defaultView.getComputedStyle(element, pseudo) : void 0;\n cache == null ? void 0 : cache.set(element, style);\n return style;\n}\nfunction isElementStyleVisibilityVisible(element, style) {\n style = style != null ? style : getElementComputedStyle(element);\n if (!style)\n return true;\n if (Element.prototype.checkVisibility && globalOptions.browserNameForWorkarounds !== "webkit") {\n if (!element.checkVisibility())\n return false;\n } else {\n const detailsOrSummary = element.closest("details,summary");\n if (detailsOrSummary !== element && (detailsOrSummary == null ? void 0 : detailsOrSummary.nodeName) === "DETAILS" && !detailsOrSummary.open)\n return false;\n }\n if (style.visibility !== "visible")\n return false;\n return true;\n}\nfunction computeBox(element) {\n const style = getElementComputedStyle(element);\n if (!style)\n return { visible: true, inline: false };\n const cursor = style.cursor;\n if (style.display === "contents") {\n for (let child = element.firstChild; child; child = child.nextSibling) {\n if (child.nodeType === 1 && isElementVisible(child))\n return { visible: true, inline: false, cursor };\n if (child.nodeType === 3 && isVisibleTextNode(child))\n return { visible: true, inline: true, cursor };\n }\n return { visible: false, inline: false, cursor };\n }\n if (!isElementStyleVisibilityVisible(element, style))\n return { cursor, visible: false, inline: false };\n const rect = element.getBoundingClientRect();\n return { cursor, visible: rect.width > 0 && rect.height > 0, inline: style.display === "inline" };\n}\nfunction isElementVisible(element) {\n return computeBox(element).visible;\n}\nfunction isVisibleTextNode(node) {\n const range = node.ownerDocument.createRange();\n range.selectNode(node);\n const rect = range.getBoundingClientRect();\n return rect.width > 0 && rect.height > 0;\n}\nfunction elementSafeTagName(element) {\n const tagName = element.tagName;\n if (typeof tagName === "string")\n return tagName.toUpperCase();\n if (element instanceof HTMLFormElement)\n return "FORM";\n return element.tagName.toUpperCase();\n}\nvar cacheStyle;\nvar cacheStyleBefore;\nvar cacheStyleAfter;\nvar cachesCounter = 0;\nfunction beginDOMCaches() {\n ++cachesCounter;\n cacheStyle != null ? cacheStyle : cacheStyle = /* @__PURE__ */ new Map();\n cacheStyleBefore != null ? cacheStyleBefore : cacheStyleBefore = /* @__PURE__ */ new Map();\n cacheStyleAfter != null ? cacheStyleAfter : cacheStyleAfter = /* @__PURE__ */ new Map();\n}\nfunction endDOMCaches() {\n if (!--cachesCounter) {\n cacheStyle = void 0;\n cacheStyleBefore = void 0;\n cacheStyleAfter = void 0;\n }\n}\n\n// packages/injected/src/roleUtils.ts\nfunction hasExplicitAccessibleName(e) {\n return e.hasAttribute("aria-label") || e.hasAttribute("aria-labelledby");\n}\nvar kAncestorPreventingLandmark = "article:not([role]), aside:not([role]), main:not([role]), nav:not([role]), section:not([role]), [role=article], [role=complementary], [role=main], [role=navigation], [role=region]";\nvar kGlobalAriaAttributes = [\n ["aria-atomic", void 0],\n ["aria-busy", void 0],\n ["aria-controls", void 0],\n ["aria-current", void 0],\n ["aria-describedby", void 0],\n ["aria-details", void 0],\n // Global use deprecated in ARIA 1.2\n // [\'aria-disabled\', undefined],\n ["aria-dropeffect", void 0],\n // Global use deprecated in ARIA 1.2\n // [\'aria-errormessage\', undefined],\n ["aria-flowto", void 0],\n ["aria-grabbed", void 0],\n // Global use deprecated in ARIA 1.2\n // [\'aria-haspopup\', undefined],\n ["aria-hidden", void 0],\n // Global use deprecated in ARIA 1.2\n // [\'aria-invalid\', undefined],\n ["aria-keyshortcuts", void 0],\n ["aria-label", ["caption", "code", "deletion", "emphasis", "generic", "insertion", "paragraph", "presentation", "strong", "subscript", "superscript"]],\n ["aria-labelledby", ["caption", "code", "deletion", "emphasis", "generic", "insertion", "paragraph", "presentation", "strong", "subscript", "superscript"]],\n ["aria-live", void 0],\n ["aria-owns", void 0],\n ["aria-relevant", void 0],\n ["aria-roledescription", ["generic"]]\n];\nfunction hasGlobalAriaAttribute(element, forRole) {\n return kGlobalAriaAttributes.some(([attr, prohibited]) => {\n return !(prohibited == null ? void 0 : prohibited.includes(forRole || "")) && element.hasAttribute(attr);\n });\n}\nfunction hasTabIndex(element) {\n return !Number.isNaN(Number(String(element.getAttribute("tabindex"))));\n}\nfunction isFocusable(element) {\n return !isNativelyDisabled(element) && (isNativelyFocusable(element) || hasTabIndex(element));\n}\nfunction isNativelyFocusable(element) {\n const tagName = elementSafeTagName(element);\n if (["BUTTON", "DETAILS", "SELECT", "TEXTAREA"].includes(tagName))\n return true;\n if (tagName === "A" || tagName === "AREA")\n return element.hasAttribute("href");\n if (tagName === "INPUT")\n return !element.hidden;\n return false;\n}\nvar kImplicitRoleByTagName = {\n "A": (e) => {\n return e.hasAttribute("href") ? "link" : null;\n },\n "AREA": (e) => {\n return e.hasAttribute("href") ? "link" : null;\n },\n "ARTICLE": () => "article",\n "ASIDE": () => "complementary",\n "BLOCKQUOTE": () => "blockquote",\n "BUTTON": () => "button",\n "CAPTION": () => "caption",\n "CODE": () => "code",\n "DATALIST": () => "listbox",\n "DD": () => "definition",\n "DEL": () => "deletion",\n "DETAILS": () => "group",\n "DFN": () => "term",\n "DIALOG": () => "dialog",\n "DT": () => "term",\n "EM": () => "emphasis",\n "FIELDSET": () => "group",\n "FIGURE": () => "figure",\n "FOOTER": (e) => closestCrossShadow(e, kAncestorPreventingLandmark) ? null : "contentinfo",\n "FORM": (e) => hasExplicitAccessibleName(e) ? "form" : null,\n "H1": () => "heading",\n "H2": () => "heading",\n "H3": () => "heading",\n "H4": () => "heading",\n "H5": () => "heading",\n "H6": () => "heading",\n "HEADER": (e) => closestCrossShadow(e, kAncestorPreventingLandmark) ? null : "banner",\n "HR": () => "separator",\n "HTML": () => "document",\n "IMG": (e) => e.getAttribute("alt") === "" && !e.getAttribute("title") && !hasGlobalAriaAttribute(e) && !hasTabIndex(e) ? "presentation" : "img",\n "INPUT": (e) => {\n const type = e.type.toLowerCase();\n if (type === "search")\n return e.hasAttribute("list") ? "combobox" : "searchbox";\n if (["email", "tel", "text", "url", ""].includes(type)) {\n const list = getIdRefs(e, e.getAttribute("list"))[0];\n return list && elementSafeTagName(list) === "DATALIST" ? "combobox" : "textbox";\n }\n if (type === "hidden")\n return null;\n if (type === "file")\n return "button";\n return inputTypeToRole[type] || "textbox";\n },\n "INS": () => "insertion",\n "LI": () => "listitem",\n "MAIN": () => "main",\n "MARK": () => "mark",\n "MATH": () => "math",\n "MENU": () => "list",\n "METER": () => "meter",\n "NAV": () => "navigation",\n "OL": () => "list",\n "OPTGROUP": () => "group",\n "OPTION": () => "option",\n "OUTPUT": () => "status",\n "P": () => "paragraph",\n "PROGRESS": () => "progressbar",\n "SEARCH": () => "search",\n "SECTION": (e) => hasExplicitAccessibleName(e) ? "region" : null,\n "SELECT": (e) => e.hasAttribute("multiple") || e.size > 1 ? "listbox" : "combobox",\n "STRONG": () => "strong",\n "SUB": () => "subscript",\n "SUP": () => "superscript",\n // For we default to Chrome behavior:\n // - Chrome reports \'img\'.\n // - Firefox reports \'diagram\' that is not in official ARIA spec yet.\n // - Safari reports \'no role\', but still computes accessible name.\n "SVG": () => "img",\n "TABLE": () => "table",\n "TBODY": () => "rowgroup",\n "TD": (e) => {\n const table = closestCrossShadow(e, "table");\n const role = table ? getExplicitAriaRole(table) : "";\n return role === "grid" || role === "treegrid" ? "gridcell" : "cell";\n },\n "TEXTAREA": () => "textbox",\n "TFOOT": () => "rowgroup",\n "TH": (e) => {\n const scope = e.getAttribute("scope");\n if (scope === "col" || scope === "colgroup")\n return "columnheader";\n if (scope === "row" || scope === "rowgroup")\n return "rowheader";\n const nextSibling = e.nextElementSibling;\n const prevSibling = e.previousElementSibling;\n const row = !!e.parentElement && elementSafeTagName(e.parentElement) === "TR" ? e.parentElement : void 0;\n if (!nextSibling && !prevSibling) {\n if (row) {\n const table = closestCrossShadow(row, "table");\n if (table && table.rows.length <= 1)\n return null;\n }\n return "columnheader";\n }\n if (isHeaderCell(nextSibling) && isHeaderCell(prevSibling))\n return "columnheader";\n if (isNonEmptyDataCell(nextSibling) || isNonEmptyDataCell(prevSibling))\n return "rowheader";\n return "columnheader";\n },\n "THEAD": () => "rowgroup",\n "TIME": () => "time",\n "TR": () => "row",\n "UL": () => "list"\n};\nfunction isHeaderCell(element) {\n return !!element && elementSafeTagName(element) === "TH";\n}\nfunction isNonEmptyDataCell(element) {\n var _a;\n if (!element || elementSafeTagName(element) !== "TD")\n return false;\n return !!(((_a = element.textContent) == null ? void 0 : _a.trim()) || element.children.length > 0);\n}\nvar kPresentationInheritanceParents = {\n "DD": ["DL", "DIV"],\n "DIV": ["DL"],\n "DT": ["DL", "DIV"],\n "LI": ["OL", "UL"],\n "TBODY": ["TABLE"],\n "TD": ["TR"],\n "TFOOT": ["TABLE"],\n "TH": ["TR"],\n "THEAD": ["TABLE"],\n "TR": ["THEAD", "TBODY", "TFOOT", "TABLE"]\n};\nfunction getImplicitAriaRole(element) {\n var _a;\n const implicitRole = ((_a = kImplicitRoleByTagName[elementSafeTagName(element)]) == null ? void 0 : _a.call(kImplicitRoleByTagName, element)) || "";\n if (!implicitRole)\n return null;\n let ancestor = element;\n while (ancestor) {\n const parent = parentElementOrShadowHost(ancestor);\n const parents = kPresentationInheritanceParents[elementSafeTagName(ancestor)];\n if (!parents || !parent || !parents.includes(elementSafeTagName(parent)))\n break;\n const parentExplicitRole = getExplicitAriaRole(parent);\n if ((parentExplicitRole === "none" || parentExplicitRole === "presentation") && !hasPresentationConflictResolution(parent, parentExplicitRole))\n return parentExplicitRole;\n ancestor = parent;\n }\n return implicitRole;\n}\nvar validRoles = [\n "alert",\n "alertdialog",\n "application",\n "article",\n "banner",\n "blockquote",\n "button",\n "caption",\n "cell",\n "checkbox",\n "code",\n "columnheader",\n "combobox",\n "complementary",\n "contentinfo",\n "definition",\n "deletion",\n "dialog",\n "directory",\n "document",\n "emphasis",\n "feed",\n "figure",\n "form",\n "generic",\n "grid",\n "gridcell",\n "group",\n "heading",\n "img",\n "insertion",\n "link",\n "list",\n "listbox",\n "listitem",\n "log",\n "main",\n "mark",\n "marquee",\n "math",\n "meter",\n "menu",\n "menubar",\n "menuitem",\n "menuitemcheckbox",\n "menuitemradio",\n "navigation",\n "none",\n "note",\n "option",\n "paragraph",\n "presentation",\n "progressbar",\n "radio",\n "radiogroup",\n "region",\n "row",\n "rowgroup",\n "rowheader",\n "scrollbar",\n "search",\n "searchbox",\n "separator",\n "slider",\n "spinbutton",\n "status",\n "strong",\n "subscript",\n "superscript",\n "switch",\n "tab",\n "table",\n "tablist",\n "tabpanel",\n "term",\n "textbox",\n "time",\n "timer",\n "toolbar",\n "tooltip",\n "tree",\n "treegrid",\n "treeitem"\n];\nfunction getExplicitAriaRole(element) {\n const roles = (element.getAttribute("role") || "").split(" ").map((role) => role.trim());\n return roles.find((role) => validRoles.includes(role)) || null;\n}\nfunction hasPresentationConflictResolution(element, role) {\n return hasGlobalAriaAttribute(element, role) || isFocusable(element);\n}\nfunction getAriaRole(element) {\n const explicitRole = getExplicitAriaRole(element);\n if (!explicitRole)\n return getImplicitAriaRole(element);\n if (explicitRole === "none" || explicitRole === "presentation") {\n const implicitRole = getImplicitAriaRole(element);\n if (hasPresentationConflictResolution(element, implicitRole))\n return implicitRole;\n }\n return explicitRole;\n}\nfunction getAriaBoolean(attr) {\n return attr === null ? void 0 : attr.toLowerCase() === "true";\n}\nfunction isElementIgnoredForAria(element) {\n return ["STYLE", "SCRIPT", "NOSCRIPT", "TEMPLATE"].includes(elementSafeTagName(element));\n}\nfunction isElementHiddenForAria(element) {\n if (isElementIgnoredForAria(element))\n return true;\n const style = getElementComputedStyle(element);\n const isSlot = element.nodeName === "SLOT";\n if ((style == null ? void 0 : style.display) === "contents" && !isSlot) {\n for (let child = element.firstChild; child; child = child.nextSibling) {\n if (child.nodeType === 1 && !isElementHiddenForAria(child))\n return false;\n if (child.nodeType === 3 && isVisibleTextNode(child))\n return false;\n }\n return true;\n }\n const isOptionInsideSelect = element.nodeName === "OPTION" && !!element.closest("select");\n if (!isOptionInsideSelect && !isSlot && !isElementStyleVisibilityVisible(element, style))\n return true;\n return belongsToDisplayNoneOrAriaHiddenOrNonSlotted(element);\n}\nfunction belongsToDisplayNoneOrAriaHiddenOrNonSlotted(element) {\n let hidden = cacheIsHidden == null ? void 0 : cacheIsHidden.get(element);\n if (hidden === void 0) {\n hidden = false;\n if (element.parentElement && element.parentElement.shadowRoot && !element.assignedSlot)\n hidden = true;\n if (!hidden) {\n const style = getElementComputedStyle(element);\n hidden = !style || style.display === "none" || getAriaBoolean(element.getAttribute("aria-hidden")) === true;\n }\n if (!hidden) {\n const parent = parentElementOrShadowHost(element);\n if (parent)\n hidden = belongsToDisplayNoneOrAriaHiddenOrNonSlotted(parent);\n }\n cacheIsHidden == null ? void 0 : cacheIsHidden.set(element, hidden);\n }\n return hidden;\n}\nfunction getIdRefs(element, ref) {\n if (!ref)\n return [];\n const root = enclosingShadowRootOrDocument(element);\n if (!root)\n return [];\n try {\n const ids = ref.split(" ").filter((id) => !!id);\n const result = [];\n for (const id of ids) {\n const firstElement = root.querySelector("#" + CSS.escape(id));\n if (firstElement && !result.includes(firstElement))\n result.push(firstElement);\n }\n return result;\n } catch (e) {\n return [];\n }\n}\nfunction trimFlatString(s) {\n return s.trim();\n}\nfunction asFlatString(s) {\n return s.split("\\xA0").map((chunk) => chunk.replace(/\\r\\n/g, "\\n").replace(/[\\u200b\\u00ad]/g, "").replace(/\\s\\s*/g, " ")).join("\\xA0").trim();\n}\nfunction queryInAriaOwned(element, selector) {\n const result = [...element.querySelectorAll(selector)];\n for (const owned of getIdRefs(element, element.getAttribute("aria-owns"))) {\n if (owned.matches(selector))\n result.push(owned);\n result.push(...owned.querySelectorAll(selector));\n }\n return result;\n}\nfunction getCSSContent(element, pseudo) {\n const cache = pseudo === "::before" ? cachePseudoContentBefore : pseudo === "::after" ? cachePseudoContentAfter : cachePseudoContent;\n if (cache == null ? void 0 : cache.has(element))\n return cache == null ? void 0 : cache.get(element);\n const style = getElementComputedStyle(element, pseudo);\n let content;\n if (style) {\n const contentValue = style.content;\n if (contentValue && contentValue !== "none" && contentValue !== "normal") {\n if (style.display !== "none" && style.visibility !== "hidden") {\n content = parseCSSContentPropertyAsString(element, contentValue, !!pseudo);\n }\n }\n }\n if (pseudo && content !== void 0) {\n const display = (style == null ? void 0 : style.display) || "inline";\n if (display !== "inline")\n content = " " + content + " ";\n }\n if (cache)\n cache.set(element, content);\n return content;\n}\nfunction parseCSSContentPropertyAsString(element, content, isPseudo) {\n if (!content || content === "none" || content === "normal") {\n return;\n }\n try {\n let tokens = tokenize(content).filter((token) => !(token instanceof WhitespaceToken));\n const delimIndex = tokens.findIndex((token) => token instanceof DelimToken && token.value === "/");\n if (delimIndex !== -1) {\n tokens = tokens.slice(delimIndex + 1);\n } else if (!isPseudo) {\n return;\n }\n const accumulated = [];\n let index = 0;\n while (index < tokens.length) {\n if (tokens[index] instanceof StringToken) {\n accumulated.push(tokens[index].value);\n index++;\n } else if (index + 2 < tokens.length && tokens[index] instanceof FunctionToken && tokens[index].value === "attr" && tokens[index + 1] instanceof IdentToken && tokens[index + 2] instanceof CloseParenToken) {\n const attrName = tokens[index + 1].value;\n accumulated.push(element.getAttribute(attrName) || "");\n index += 3;\n } else {\n return;\n }\n }\n return accumulated.join("");\n } catch {\n }\n}\nfunction getAriaLabelledByElements(element) {\n const ref = element.getAttribute("aria-labelledby");\n if (ref === null)\n return null;\n const refs = getIdRefs(element, ref);\n return refs.length ? refs : null;\n}\nfunction allowsNameFromContent(role, targetDescendant) {\n const alwaysAllowsNameFromContent = ["button", "cell", "checkbox", "columnheader", "gridcell", "heading", "link", "menuitem", "menuitemcheckbox", "menuitemradio", "option", "radio", "row", "rowheader", "switch", "tab", "tooltip", "treeitem"].includes(role);\n const descendantAllowsNameFromContent = targetDescendant && ["", "caption", "code", "contentinfo", "definition", "deletion", "emphasis", "insertion", "list", "listitem", "mark", "none", "paragraph", "presentation", "region", "row", "rowgroup", "section", "strong", "subscript", "superscript", "table", "term", "time"].includes(role);\n return alwaysAllowsNameFromContent || descendantAllowsNameFromContent;\n}\nfunction getElementAccessibleName(element, includeHidden) {\n const cache = includeHidden ? cacheAccessibleNameHidden : cacheAccessibleName;\n let accessibleName = cache == null ? void 0 : cache.get(element);\n if (accessibleName === void 0) {\n accessibleName = "";\n const elementProhibitsNaming = ["caption", "code", "definition", "deletion", "emphasis", "generic", "insertion", "mark", "paragraph", "presentation", "strong", "subscript", "suggestion", "superscript", "term", "time"].includes(getAriaRole(element) || "");\n if (!elementProhibitsNaming) {\n accessibleName = asFlatString(getTextAlternativeInternal(element, {\n includeHidden,\n visitedElements: /* @__PURE__ */ new Set(),\n embeddedInTargetElement: "self"\n }));\n }\n cache == null ? void 0 : cache.set(element, accessibleName);\n }\n return accessibleName;\n}\nfunction getElementAccessibleDescription(element, includeHidden) {\n const cache = includeHidden ? cacheAccessibleDescriptionHidden : cacheAccessibleDescription;\n let accessibleDescription = cache == null ? void 0 : cache.get(element);\n if (accessibleDescription === void 0) {\n accessibleDescription = "";\n if (element.hasAttribute("aria-describedby")) {\n const describedBy = getIdRefs(element, element.getAttribute("aria-describedby"));\n accessibleDescription = asFlatString(describedBy.map((ref) => getTextAlternativeInternal(ref, {\n includeHidden,\n visitedElements: /* @__PURE__ */ new Set(),\n embeddedInDescribedBy: { element: ref, hidden: isElementHiddenForAria(ref) }\n })).join(" "));\n } else if (element.hasAttribute("aria-description")) {\n accessibleDescription = asFlatString(element.getAttribute("aria-description") || "");\n } else {\n accessibleDescription = asFlatString(element.getAttribute("title") || "");\n }\n cache == null ? void 0 : cache.set(element, accessibleDescription);\n }\n return accessibleDescription;\n}\nvar kAriaInvalidRoles = [\n "application",\n "checkbox",\n "columnheader",\n "combobox",\n "gridcell",\n "listbox",\n "radiogroup",\n "rowheader",\n "searchbox",\n "slider",\n "spinbutton",\n "switch",\n "textbox",\n "tree"\n];\nfunction getAriaInvalid(element) {\n const ariaInvalid = element.getAttribute("aria-invalid");\n if (!ariaInvalid || ariaInvalid.trim() === "" || ariaInvalid.toLocaleLowerCase() === "false")\n return "false";\n if (ariaInvalid === "true" || ariaInvalid === "grammar" || ariaInvalid === "spelling")\n return ariaInvalid;\n return "true";\n}\nfunction getValidityInvalid(element) {\n if ("validity" in element) {\n const validity = element.validity;\n return (validity == null ? void 0 : validity.valid) === false;\n }\n return false;\n}\nfunction getElementAccessibleErrorMessage(element) {\n const cache = cacheAccessibleErrorMessage;\n let accessibleErrorMessage = cacheAccessibleErrorMessage == null ? void 0 : cacheAccessibleErrorMessage.get(element);\n if (accessibleErrorMessage === void 0) {\n accessibleErrorMessage = "";\n const isAriaInvalid = getAriaInvalid(element) !== "false";\n const isValidityInvalid = getValidityInvalid(element);\n if (isAriaInvalid || isValidityInvalid) {\n const errorMessageId = element.getAttribute("aria-errormessage");\n const errorMessages = getIdRefs(element, errorMessageId);\n const parts = errorMessages.map((errorMessage) => asFlatString(\n getTextAlternativeInternal(errorMessage, {\n visitedElements: /* @__PURE__ */ new Set(),\n embeddedInDescribedBy: { element: errorMessage, hidden: isElementHiddenForAria(errorMessage) }\n })\n ));\n accessibleErrorMessage = parts.join(" ").trim();\n }\n cache == null ? void 0 : cache.set(element, accessibleErrorMessage);\n }\n return accessibleErrorMessage;\n}\nfunction getTextAlternativeInternal(element, options) {\n var _a, _b, _c, _d;\n if (options.visitedElements.has(element))\n return "";\n const childOptions = {\n ...options,\n embeddedInTargetElement: options.embeddedInTargetElement === "self" ? "descendant" : options.embeddedInTargetElement\n };\n if (!options.includeHidden) {\n const isEmbeddedInHiddenReferenceTraversal = !!((_a = options.embeddedInLabelledBy) == null ? void 0 : _a.hidden) || !!((_b = options.embeddedInDescribedBy) == null ? void 0 : _b.hidden) || !!((_c = options.embeddedInNativeTextAlternative) == null ? void 0 : _c.hidden) || !!((_d = options.embeddedInLabel) == null ? void 0 : _d.hidden);\n if (isElementIgnoredForAria(element) || !isEmbeddedInHiddenReferenceTraversal && isElementHiddenForAria(element)) {\n options.visitedElements.add(element);\n return "";\n }\n }\n const labelledBy = getAriaLabelledByElements(element);\n if (!options.embeddedInLabelledBy) {\n const accessibleName = (labelledBy || []).map((ref) => getTextAlternativeInternal(ref, {\n ...options,\n embeddedInLabelledBy: { element: ref, hidden: isElementHiddenForAria(ref) },\n embeddedInDescribedBy: void 0,\n embeddedInTargetElement: void 0,\n embeddedInLabel: void 0,\n embeddedInNativeTextAlternative: void 0\n })).join(" ");\n if (accessibleName)\n return accessibleName;\n }\n const role = getAriaRole(element) || "";\n const tagName = elementSafeTagName(element);\n if (!!options.embeddedInLabel || !!options.embeddedInLabelledBy || options.embeddedInTargetElement === "descendant") {\n const isOwnLabel = [...element.labels || []].includes(element);\n const isOwnLabelledBy = (labelledBy || []).includes(element);\n if (!isOwnLabel && !isOwnLabelledBy) {\n if (role === "textbox") {\n options.visitedElements.add(element);\n if (tagName === "INPUT" || tagName === "TEXTAREA")\n return element.value;\n return element.textContent || "";\n }\n if (["combobox", "listbox"].includes(role)) {\n options.visitedElements.add(element);\n let selectedOptions;\n if (tagName === "SELECT") {\n selectedOptions = [...element.selectedOptions];\n if (!selectedOptions.length && element.options.length)\n selectedOptions.push(element.options[0]);\n } else {\n const listbox = role === "combobox" ? queryInAriaOwned(element, "*").find((e) => getAriaRole(e) === "listbox") : element;\n selectedOptions = listbox ? queryInAriaOwned(listbox, \'[aria-selected="true"]\').filter((e) => getAriaRole(e) === "option") : [];\n }\n if (!selectedOptions.length && tagName === "INPUT") {\n return element.value;\n }\n return selectedOptions.map((option) => getTextAlternativeInternal(option, childOptions)).join(" ");\n }\n if (["progressbar", "scrollbar", "slider", "spinbutton", "meter"].includes(role)) {\n options.visitedElements.add(element);\n if (element.hasAttribute("aria-valuetext"))\n return element.getAttribute("aria-valuetext") || "";\n if (element.hasAttribute("aria-valuenow"))\n return element.getAttribute("aria-valuenow") || "";\n return element.getAttribute("value") || "";\n }\n if (["menu"].includes(role)) {\n options.visitedElements.add(element);\n return "";\n }\n }\n }\n const ariaLabel = element.getAttribute("aria-label") || "";\n if (trimFlatString(ariaLabel)) {\n options.visitedElements.add(element);\n return ariaLabel;\n }\n if (!["presentation", "none"].includes(role)) {\n if (tagName === "INPUT" && ["button", "submit", "reset"].includes(element.type)) {\n options.visitedElements.add(element);\n const value = element.value || "";\n if (trimFlatString(value))\n return value;\n if (element.type === "submit")\n return "Submit";\n if (element.type === "reset")\n return "Reset";\n const title = element.getAttribute("title") || "";\n return title;\n }\n if (tagName === "INPUT" && element.type === "file") {\n options.visitedElements.add(element);\n const labels = element.labels || [];\n if (labels.length && !options.embeddedInLabelledBy)\n return getAccessibleNameFromAssociatedLabels(labels, options);\n return "Choose File";\n }\n if (tagName === "INPUT" && element.type === "image") {\n options.visitedElements.add(element);\n const labels = element.labels || [];\n if (labels.length && !options.embeddedInLabelledBy)\n return getAccessibleNameFromAssociatedLabels(labels, options);\n const alt = element.getAttribute("alt") || "";\n if (trimFlatString(alt))\n return alt;\n const title = element.getAttribute("title") || "";\n if (trimFlatString(title))\n return title;\n return "Submit";\n }\n if (!labelledBy && tagName === "BUTTON") {\n options.visitedElements.add(element);\n const labels = element.labels || [];\n if (labels.length)\n return getAccessibleNameFromAssociatedLabels(labels, options);\n }\n if (!labelledBy && tagName === "OUTPUT") {\n options.visitedElements.add(element);\n const labels = element.labels || [];\n if (labels.length)\n return getAccessibleNameFromAssociatedLabels(labels, options);\n return element.getAttribute("title") || "";\n }\n if (!labelledBy && (tagName === "TEXTAREA" || tagName === "SELECT" || tagName === "INPUT")) {\n options.visitedElements.add(element);\n const labels = element.labels || [];\n if (labels.length)\n return getAccessibleNameFromAssociatedLabels(labels, options);\n const usePlaceholder = tagName === "INPUT" && ["text", "password", "search", "tel", "email", "url"].includes(element.type) || tagName === "TEXTAREA";\n const placeholder = element.getAttribute("placeholder") || "";\n const title = element.getAttribute("title") || "";\n if (!usePlaceholder || title)\n return title;\n return placeholder;\n }\n if (!labelledBy && tagName === "FIELDSET") {\n options.visitedElements.add(element);\n for (let child = element.firstElementChild; child; child = child.nextElementSibling) {\n if (elementSafeTagName(child) === "LEGEND") {\n return getTextAlternativeInternal(child, {\n ...childOptions,\n embeddedInNativeTextAlternative: { element: child, hidden: isElementHiddenForAria(child) }\n });\n }\n }\n const title = element.getAttribute("title") || "";\n return title;\n }\n if (!labelledBy && tagName === "FIGURE") {\n options.visitedElements.add(element);\n for (let child = element.firstElementChild; child; child = child.nextElementSibling) {\n if (elementSafeTagName(child) === "FIGCAPTION") {\n return getTextAlternativeInternal(child, {\n ...childOptions,\n embeddedInNativeTextAlternative: { element: child, hidden: isElementHiddenForAria(child) }\n });\n }\n }\n const title = element.getAttribute("title") || "";\n return title;\n }\n if (tagName === "IMG") {\n options.visitedElements.add(element);\n const alt = element.getAttribute("alt") || "";\n if (trimFlatString(alt))\n return alt;\n const title = element.getAttribute("title") || "";\n return title;\n }\n if (tagName === "TABLE") {\n options.visitedElements.add(element);\n for (let child = element.firstElementChild; child; child = child.nextElementSibling) {\n if (elementSafeTagName(child) === "CAPTION") {\n return getTextAlternativeInternal(child, {\n ...childOptions,\n embeddedInNativeTextAlternative: { element: child, hidden: isElementHiddenForAria(child) }\n });\n }\n }\n const summary = element.getAttribute("summary") || "";\n if (summary)\n return summary;\n }\n if (tagName === "AREA") {\n options.visitedElements.add(element);\n const alt = element.getAttribute("alt") || "";\n if (trimFlatString(alt))\n return alt;\n const title = element.getAttribute("title") || "";\n return title;\n }\n if (tagName === "SVG" || element.ownerSVGElement) {\n options.visitedElements.add(element);\n for (let child = element.firstElementChild; child; child = child.nextElementSibling) {\n if (elementSafeTagName(child) === "TITLE" && child.ownerSVGElement) {\n return getTextAlternativeInternal(child, {\n ...childOptions,\n embeddedInLabelledBy: { element: child, hidden: isElementHiddenForAria(child) }\n });\n }\n }\n }\n if (element.ownerSVGElement && tagName === "A") {\n const title = element.getAttribute("xlink:title") || "";\n if (trimFlatString(title)) {\n options.visitedElements.add(element);\n return title;\n }\n }\n }\n const shouldNameFromContentForSummary = tagName === "SUMMARY" && !["presentation", "none"].includes(role);\n if (allowsNameFromContent(role, options.embeddedInTargetElement === "descendant") || shouldNameFromContentForSummary || !!options.embeddedInLabelledBy || !!options.embeddedInDescribedBy || !!options.embeddedInLabel || !!options.embeddedInNativeTextAlternative) {\n options.visitedElements.add(element);\n const accessibleName = innerAccumulatedElementText(element, childOptions);\n const maybeTrimmedAccessibleName = options.embeddedInTargetElement === "self" ? trimFlatString(accessibleName) : accessibleName;\n if (maybeTrimmedAccessibleName)\n return accessibleName;\n }\n if (!["presentation", "none"].includes(role) || tagName === "IFRAME") {\n options.visitedElements.add(element);\n const title = element.getAttribute("title") || "";\n if (trimFlatString(title))\n return title;\n }\n options.visitedElements.add(element);\n return "";\n}\nfunction innerAccumulatedElementText(element, options) {\n const tokens = [];\n const visit = (node, skipSlotted) => {\n var _a;\n if (skipSlotted && node.assignedSlot)\n return;\n if (node.nodeType === 1) {\n const display = ((_a = getElementComputedStyle(node)) == null ? void 0 : _a.display) || "inline";\n let token = getTextAlternativeInternal(node, options);\n if (display !== "inline" || node.nodeName === "BR")\n token = " " + token + " ";\n tokens.push(token);\n } else if (node.nodeType === 3) {\n tokens.push(node.textContent || "");\n }\n };\n tokens.push(getCSSContent(element, "::before") || "");\n const content = getCSSContent(element);\n if (content !== void 0) {\n tokens.push(content);\n } else {\n const assignedNodes = element.nodeName === "SLOT" ? element.assignedNodes() : [];\n if (assignedNodes.length) {\n for (const child of assignedNodes)\n visit(child, false);\n } else {\n for (let child = element.firstChild; child; child = child.nextSibling)\n visit(child, true);\n if (element.shadowRoot) {\n for (let child = element.shadowRoot.firstChild; child; child = child.nextSibling)\n visit(child, true);\n }\n for (const owned of getIdRefs(element, element.getAttribute("aria-owns")))\n visit(owned, true);\n }\n }\n tokens.push(getCSSContent(element, "::after") || "");\n return tokens.join("");\n}\nvar kAriaSelectedRoles = ["gridcell", "option", "row", "tab", "rowheader", "columnheader", "treeitem"];\nfunction getAriaSelected(element) {\n if (elementSafeTagName(element) === "OPTION")\n return element.selected;\n if (kAriaSelectedRoles.includes(getAriaRole(element) || ""))\n return getAriaBoolean(element.getAttribute("aria-selected")) === true;\n return false;\n}\nvar kAriaCheckedRoles = ["checkbox", "menuitemcheckbox", "option", "radio", "switch", "menuitemradio", "treeitem"];\nfunction getAriaChecked(element) {\n const result = getChecked(element, true);\n return result === "error" ? false : result;\n}\nfunction getCheckedAllowMixed(element) {\n return getChecked(element, true);\n}\nfunction getCheckedWithoutMixed(element) {\n const result = getChecked(element, false);\n return result;\n}\nfunction getChecked(element, allowMixed) {\n const tagName = elementSafeTagName(element);\n if (allowMixed && tagName === "INPUT" && element.indeterminate)\n return "mixed";\n if (tagName === "INPUT" && ["checkbox", "radio"].includes(element.type))\n return element.checked;\n if (kAriaCheckedRoles.includes(getAriaRole(element) || "")) {\n const checked = element.getAttribute("aria-checked");\n if (checked === "true")\n return true;\n if (allowMixed && checked === "mixed")\n return "mixed";\n return false;\n }\n return "error";\n}\nvar kAriaReadonlyRoles = ["checkbox", "combobox", "grid", "gridcell", "listbox", "radiogroup", "slider", "spinbutton", "textbox", "columnheader", "rowheader", "searchbox", "switch", "treegrid"];\nfunction getReadonly(element) {\n const tagName = elementSafeTagName(element);\n if (["INPUT", "TEXTAREA", "SELECT"].includes(tagName))\n return element.hasAttribute("readonly");\n if (kAriaReadonlyRoles.includes(getAriaRole(element) || ""))\n return element.getAttribute("aria-readonly") === "true";\n if (element.isContentEditable)\n return false;\n return "error";\n}\nvar kAriaPressedRoles = ["button"];\nfunction getAriaPressed(element) {\n if (kAriaPressedRoles.includes(getAriaRole(element) || "")) {\n const pressed = element.getAttribute("aria-pressed");\n if (pressed === "true")\n return true;\n if (pressed === "mixed")\n return "mixed";\n }\n return false;\n}\nvar kAriaExpandedRoles = ["application", "button", "checkbox", "combobox", "gridcell", "link", "listbox", "menuitem", "row", "rowheader", "tab", "treeitem", "columnheader", "menuitemcheckbox", "menuitemradio", "rowheader", "switch"];\nfunction getAriaExpanded(element) {\n if (elementSafeTagName(element) === "DETAILS")\n return element.open;\n if (kAriaExpandedRoles.includes(getAriaRole(element) || "")) {\n const expanded = element.getAttribute("aria-expanded");\n if (expanded === null)\n return void 0;\n if (expanded === "true")\n return true;\n return false;\n }\n return void 0;\n}\nvar kAriaLevelRoles = ["heading", "listitem", "row", "treeitem"];\nfunction getAriaLevel(element) {\n const native = { "H1": 1, "H2": 2, "H3": 3, "H4": 4, "H5": 5, "H6": 6 }[elementSafeTagName(element)];\n if (native)\n return native;\n if (kAriaLevelRoles.includes(getAriaRole(element) || "")) {\n const attr = element.getAttribute("aria-level");\n const value = attr === null ? Number.NaN : Number(attr);\n if (Number.isInteger(value) && value >= 1)\n return value;\n }\n return 0;\n}\nvar kAriaDisabledRoles = ["application", "button", "composite", "gridcell", "group", "input", "link", "menuitem", "scrollbar", "separator", "tab", "checkbox", "columnheader", "combobox", "grid", "listbox", "menu", "menubar", "menuitemcheckbox", "menuitemradio", "option", "radio", "radiogroup", "row", "rowheader", "searchbox", "select", "slider", "spinbutton", "switch", "tablist", "textbox", "toolbar", "tree", "treegrid", "treeitem"];\nfunction getAriaDisabled(element) {\n return isNativelyDisabled(element) || hasExplicitAriaDisabled(element);\n}\nfunction isNativelyDisabled(element) {\n const isNativeFormControl = ["BUTTON", "INPUT", "SELECT", "TEXTAREA", "OPTION", "OPTGROUP"].includes(elementSafeTagName(element));\n return isNativeFormControl && (element.hasAttribute("disabled") || belongsToDisabledOptGroup(element) || belongsToDisabledFieldSet(element));\n}\nfunction belongsToDisabledOptGroup(element) {\n return elementSafeTagName(element) === "OPTION" && !!element.closest("OPTGROUP[DISABLED]");\n}\nfunction belongsToDisabledFieldSet(element) {\n const fieldSetElement = element == null ? void 0 : element.closest("FIELDSET[DISABLED]");\n if (!fieldSetElement)\n return false;\n const legendElement = fieldSetElement.querySelector(":scope > LEGEND");\n return !legendElement || !legendElement.contains(element);\n}\nfunction hasExplicitAriaDisabled(element, isAncestor = false) {\n if (!element)\n return false;\n if (isAncestor || kAriaDisabledRoles.includes(getAriaRole(element) || "")) {\n const attribute = (element.getAttribute("aria-disabled") || "").toLowerCase();\n if (attribute === "true")\n return true;\n if (attribute === "false")\n return false;\n return hasExplicitAriaDisabled(parentElementOrShadowHost(element), true);\n }\n return false;\n}\nfunction getAccessibleNameFromAssociatedLabels(labels, options) {\n return [...labels].map((label) => getTextAlternativeInternal(label, {\n ...options,\n embeddedInLabel: { element: label, hidden: isElementHiddenForAria(label) },\n embeddedInNativeTextAlternative: void 0,\n embeddedInLabelledBy: void 0,\n embeddedInDescribedBy: void 0,\n embeddedInTargetElement: void 0\n })).filter((accessibleName) => !!accessibleName).join(" ");\n}\nfunction receivesPointerEvents(element) {\n const cache = cachePointerEvents;\n let e = element;\n let result;\n const parents = [];\n for (; e; e = parentElementOrShadowHost(e)) {\n const cached = cache.get(e);\n if (cached !== void 0) {\n result = cached;\n break;\n }\n parents.push(e);\n const style = getElementComputedStyle(e);\n if (!style) {\n result = true;\n break;\n }\n const value = style.pointerEvents;\n if (value) {\n result = value !== "none";\n break;\n }\n }\n if (result === void 0)\n result = true;\n for (const parent of parents)\n cache.set(parent, result);\n return result;\n}\nvar cacheAccessibleName;\nvar cacheAccessibleNameHidden;\nvar cacheAccessibleDescription;\nvar cacheAccessibleDescriptionHidden;\nvar cacheAccessibleErrorMessage;\nvar cacheIsHidden;\nvar cachePseudoContent;\nvar cachePseudoContentBefore;\nvar cachePseudoContentAfter;\nvar cachePointerEvents;\nvar cachesCounter2 = 0;\nfunction beginAriaCaches() {\n beginDOMCaches();\n ++cachesCounter2;\n cacheAccessibleName != null ? cacheAccessibleName : cacheAccessibleName = /* @__PURE__ */ new Map();\n cacheAccessibleNameHidden != null ? cacheAccessibleNameHidden : cacheAccessibleNameHidden = /* @__PURE__ */ new Map();\n cacheAccessibleDescription != null ? cacheAccessibleDescription : cacheAccessibleDescription = /* @__PURE__ */ new Map();\n cacheAccessibleDescriptionHidden != null ? cacheAccessibleDescriptionHidden : cacheAccessibleDescriptionHidden = /* @__PURE__ */ new Map();\n cacheAccessibleErrorMessage != null ? cacheAccessibleErrorMessage : cacheAccessibleErrorMessage = /* @__PURE__ */ new Map();\n cacheIsHidden != null ? cacheIsHidden : cacheIsHidden = /* @__PURE__ */ new Map();\n cachePseudoContent != null ? cachePseudoContent : cachePseudoContent = /* @__PURE__ */ new Map();\n cachePseudoContentBefore != null ? cachePseudoContentBefore : cachePseudoContentBefore = /* @__PURE__ */ new Map();\n cachePseudoContentAfter != null ? cachePseudoContentAfter : cachePseudoContentAfter = /* @__PURE__ */ new Map();\n cachePointerEvents != null ? cachePointerEvents : cachePointerEvents = /* @__PURE__ */ new Map();\n}\nfunction endAriaCaches() {\n if (!--cachesCounter2) {\n cacheAccessibleName = void 0;\n cacheAccessibleNameHidden = void 0;\n cacheAccessibleDescription = void 0;\n cacheAccessibleDescriptionHidden = void 0;\n cacheAccessibleErrorMessage = void 0;\n cacheIsHidden = void 0;\n cachePseudoContent = void 0;\n cachePseudoContentBefore = void 0;\n cachePseudoContentAfter = void 0;\n cachePointerEvents = void 0;\n }\n endDOMCaches();\n}\nvar inputTypeToRole = {\n "button": "button",\n "checkbox": "checkbox",\n "image": "button",\n "number": "spinbutton",\n "radio": "radio",\n "range": "slider",\n "reset": "button",\n "submit": "button"\n};\n\n// packages/injected/src/ariaSnapshot.ts\nvar lastRef = 0;\nfunction toInternalOptions(options) {\n const renderBoxes = options.boxes;\n if (options.mode === "ai") {\n return {\n visibility: "ariaOrVisible",\n refs: "interactable",\n refPrefix: options.refPrefix,\n includeGenericRole: true,\n renderActive: !options.doNotRenderActive,\n renderCursorPointer: true,\n renderBoxes\n };\n }\n if (options.mode === "autoexpect") {\n return { visibility: "ariaAndVisible", refs: "none", renderBoxes };\n }\n if (options.mode === "codegen") {\n return { visibility: "aria", refs: "none", renderStringsAsRegex: true, renderBoxes };\n }\n return { visibility: "aria", refs: "none", renderBoxes };\n}\nfunction generateAriaTree(rootElement, publicOptions) {\n const options = toInternalOptions(publicOptions);\n const visited = /* @__PURE__ */ new Set();\n const snapshot = {\n root: { role: "fragment", name: "", children: [], props: {}, box: computeBox(rootElement), receivesPointerEvents: true },\n elements: /* @__PURE__ */ new Map(),\n refs: /* @__PURE__ */ new Map(),\n iframeRefs: []\n };\n setAriaNodeElement(snapshot.root, rootElement);\n const visit = (ariaNode, node, parentElementVisible) => {\n if (visited.has(node))\n return;\n visited.add(node);\n if (node.nodeType === Node.TEXT_NODE && node.nodeValue) {\n if (!parentElementVisible)\n return;\n const text = node.nodeValue;\n if (ariaNode.role !== "textbox" && text)\n ariaNode.children.push(node.nodeValue || "");\n return;\n }\n if (node.nodeType !== Node.ELEMENT_NODE)\n return;\n const element = node;\n const isElementVisibleForAria = !isElementHiddenForAria(element);\n let visible = isElementVisibleForAria;\n if (options.visibility === "ariaOrVisible")\n visible = isElementVisibleForAria || isElementVisible(element);\n if (options.visibility === "ariaAndVisible")\n visible = isElementVisibleForAria && isElementVisible(element);\n if (options.visibility === "aria" && !visible)\n return;\n const ariaChildren = [];\n if (element.hasAttribute("aria-owns")) {\n const ids = element.getAttribute("aria-owns").split(/\\s+/);\n for (const id of ids) {\n const ownedElement = rootElement.ownerDocument.getElementById(id);\n if (ownedElement)\n ariaChildren.push(ownedElement);\n }\n }\n const childAriaNode = visible ? toAriaNode(element, options) : null;\n if (childAriaNode) {\n if (childAriaNode.ref) {\n snapshot.elements.set(childAriaNode.ref, element);\n snapshot.refs.set(element, childAriaNode.ref);\n if (childAriaNode.role === "iframe")\n snapshot.iframeRefs.push(childAriaNode.ref);\n }\n ariaNode.children.push(childAriaNode);\n }\n processElement(childAriaNode || ariaNode, element, ariaChildren, visible);\n };\n function processElement(ariaNode, element, ariaChildren, parentElementVisible) {\n var _a;\n const display = ((_a = getElementComputedStyle(element)) == null ? void 0 : _a.display) || "inline";\n const treatAsBlock = display !== "inline" || element.nodeName === "BR" ? " " : "";\n if (treatAsBlock)\n ariaNode.children.push(treatAsBlock);\n ariaNode.children.push(getCSSContent(element, "::before") || "");\n const assignedNodes = element.nodeName === "SLOT" ? element.assignedNodes() : [];\n if (assignedNodes.length) {\n for (const child of assignedNodes)\n visit(ariaNode, child, parentElementVisible);\n } else {\n for (let child = element.firstChild; child; child = child.nextSibling) {\n if (!child.assignedSlot)\n visit(ariaNode, child, parentElementVisible);\n }\n if (element.shadowRoot) {\n for (let child = element.shadowRoot.firstChild; child; child = child.nextSibling)\n visit(ariaNode, child, parentElementVisible);\n }\n }\n for (const child of ariaChildren)\n visit(ariaNode, child, parentElementVisible);\n ariaNode.children.push(getCSSContent(element, "::after") || "");\n if (treatAsBlock)\n ariaNode.children.push(treatAsBlock);\n if (ariaNode.children.length === 1 && ariaNode.name === ariaNode.children[0])\n ariaNode.children = [];\n if (ariaNode.role === "link" && element.hasAttribute("href")) {\n const href = element.getAttribute("href");\n ariaNode.props["url"] = href;\n }\n if (ariaNode.role === "textbox" && element.hasAttribute("placeholder") && element.getAttribute("placeholder") !== ariaNode.name) {\n const placeholder = element.getAttribute("placeholder");\n ariaNode.props["placeholder"] = placeholder;\n }\n }\n beginAriaCaches();\n try {\n visit(snapshot.root, rootElement, true);\n } finally {\n endAriaCaches();\n }\n normalizeStringChildren(snapshot.root);\n normalizeGenericRoles(snapshot.root);\n return snapshot;\n}\nfunction computeAriaRef(ariaNode, options) {\n var _a;\n if (options.refs === "none")\n return;\n if (options.refs === "interactable" && (!ariaNode.box.visible || !ariaNode.receivesPointerEvents))\n return;\n const element = ariaNodeElement(ariaNode);\n let ariaRef = element._ariaRef;\n if (!ariaRef || ariaRef.role !== ariaNode.role || ariaRef.name !== ariaNode.name) {\n ariaRef = { role: ariaNode.role, name: ariaNode.name, ref: ((_a = options.refPrefix) != null ? _a : "") + "e" + ++lastRef };\n element._ariaRef = ariaRef;\n }\n ariaNode.ref = ariaRef.ref;\n}\nfunction toAriaNode(element, options) {\n var _a;\n const active = element.ownerDocument.activeElement === element;\n if (element.nodeName === "IFRAME") {\n const ariaNode = {\n role: "iframe",\n name: "",\n children: [],\n props: {},\n box: computeBox(element),\n receivesPointerEvents: true,\n active\n };\n setAriaNodeElement(ariaNode, element);\n computeAriaRef(ariaNode, options);\n return ariaNode;\n }\n const defaultRole = options.includeGenericRole ? "generic" : null;\n const role = (_a = getAriaRole(element)) != null ? _a : defaultRole;\n if (!role || role === "presentation" || role === "none")\n return null;\n const name = normalizeWhiteSpace(getElementAccessibleName(element, false) || "");\n const receivesPointerEvents2 = receivesPointerEvents(element);\n const box = computeBox(element);\n if (role === "generic" && box.inline && element.childNodes.length === 1 && element.childNodes[0].nodeType === Node.TEXT_NODE)\n return null;\n const result = {\n role,\n name,\n children: [],\n props: {},\n box,\n receivesPointerEvents: receivesPointerEvents2,\n active\n };\n setAriaNodeElement(result, element);\n computeAriaRef(result, options);\n if (kAriaCheckedRoles.includes(role))\n result.checked = getAriaChecked(element);\n if (kAriaDisabledRoles.includes(role))\n result.disabled = getAriaDisabled(element);\n if (kAriaExpandedRoles.includes(role))\n result.expanded = getAriaExpanded(element);\n if (kAriaInvalidRoles.includes(role)) {\n const invalid = getAriaInvalid(element);\n result.invalid = invalid === "false" ? false : invalid === "true" ? true : invalid;\n }\n if (kAriaLevelRoles.includes(role))\n result.level = getAriaLevel(element);\n if (kAriaPressedRoles.includes(role))\n result.pressed = getAriaPressed(element);\n if (kAriaSelectedRoles.includes(role))\n result.selected = getAriaSelected(element);\n if (element instanceof HTMLInputElement || element instanceof HTMLTextAreaElement) {\n if (element.type !== "checkbox" && element.type !== "radio" && element.type !== "file")\n result.children = [element.value];\n }\n return result;\n}\nfunction normalizeGenericRoles(node) {\n const normalizeChildren = (node2) => {\n const result = [];\n for (const child of node2.children || []) {\n if (typeof child === "string") {\n result.push(child);\n continue;\n }\n const normalized = normalizeChildren(child);\n result.push(...normalized);\n }\n const removeSelf = node2.role === "generic" && !node2.name && result.length <= 1 && result.every((c) => typeof c !== "string" && !!c.ref);\n if (removeSelf)\n return result;\n node2.children = result;\n return [node2];\n };\n normalizeChildren(node);\n}\nfunction normalizeStringChildren(rootA11yNode) {\n const flushChildren = (buffer, normalizedChildren) => {\n if (!buffer.length)\n return;\n const text = normalizeWhiteSpace(buffer.join(""));\n if (text)\n normalizedChildren.push(text);\n buffer.length = 0;\n };\n const visit = (ariaNode) => {\n const normalizedChildren = [];\n const buffer = [];\n for (const child of ariaNode.children || []) {\n if (typeof child === "string") {\n buffer.push(child);\n } else {\n flushChildren(buffer, normalizedChildren);\n visit(child);\n normalizedChildren.push(child);\n }\n }\n flushChildren(buffer, normalizedChildren);\n ariaNode.children = normalizedChildren.length ? normalizedChildren : [];\n if (ariaNode.children.length === 1 && ariaNode.children[0] === ariaNode.name)\n ariaNode.children = [];\n };\n visit(rootA11yNode);\n}\nfunction matchesStringOrRegex(text, template) {\n if (!template)\n return true;\n if (!text)\n return false;\n if (typeof template === "string")\n return text === template;\n return !!text.match(new RegExp(template.pattern));\n}\nfunction matchesTextValue(text, template) {\n if (!(template == null ? void 0 : template.normalized))\n return true;\n if (!text)\n return false;\n if (text === template.normalized)\n return true;\n if (text === template.raw)\n return true;\n const regex = cachedRegex(template);\n if (regex)\n return !!text.match(regex);\n return false;\n}\nvar cachedRegexSymbol = Symbol("cachedRegex");\nfunction cachedRegex(template) {\n if (template[cachedRegexSymbol] !== void 0)\n return template[cachedRegexSymbol];\n const { raw } = template;\n const canBeRegex = raw.startsWith("/") && raw.endsWith("/") && raw.length > 1;\n let regex;\n try {\n regex = canBeRegex ? new RegExp(raw.slice(1, -1)) : null;\n } catch (e) {\n regex = null;\n }\n template[cachedRegexSymbol] = regex;\n return regex;\n}\nfunction matchesExpectAriaTemplate(rootElement, template) {\n const snapshot = generateAriaTree(rootElement, { mode: "default" });\n const matches = matchesNodeDeep(snapshot.root, template, false, false);\n return {\n matches,\n received: {\n raw: renderAriaTree(snapshot, { mode: "default" }).text,\n regex: renderAriaTree(snapshot, { mode: "codegen" }).text\n }\n };\n}\nfunction getAllElementsMatchingExpectAriaTemplate(rootElement, template) {\n const root = generateAriaTree(rootElement, { mode: "default" }).root;\n const matches = matchesNodeDeep(root, template, true, false);\n return matches.map((n) => ariaNodeElement(n));\n}\nfunction matchesNode(node, template, isDeepEqual) {\n var _a;\n if (typeof node === "string" && template.kind === "text")\n return matchesTextValue(node, template.text);\n if (node === null || typeof node !== "object" || template.kind !== "role")\n return false;\n if (template.role !== "fragment" && template.role !== node.role)\n return false;\n if (template.checked !== void 0 && template.checked !== node.checked)\n return false;\n if (template.disabled !== void 0 && template.disabled !== node.disabled)\n return false;\n if (template.expanded !== void 0 && template.expanded !== node.expanded)\n return false;\n if (template.invalid !== void 0 && template.invalid !== node.invalid)\n return false;\n if (template.level !== void 0 && template.level !== node.level)\n return false;\n if (template.pressed !== void 0 && template.pressed !== node.pressed)\n return false;\n if (template.selected !== void 0 && template.selected !== node.selected)\n return false;\n if (!matchesStringOrRegex(node.name, template.name))\n return false;\n if (!matchesTextValue(node.props.url, (_a = template.props) == null ? void 0 : _a.url))\n return false;\n if (template.containerMode === "contain")\n return containsList(node.children || [], template.children || []);\n if (template.containerMode === "equal")\n return listEqual(node.children || [], template.children || [], false);\n if (template.containerMode === "deep-equal" || isDeepEqual)\n return listEqual(node.children || [], template.children || [], true);\n return containsList(node.children || [], template.children || []);\n}\nfunction listEqual(children, template, isDeepEqual) {\n if (template.length !== children.length)\n return false;\n for (let i = 0; i < template.length; ++i) {\n if (!matchesNode(children[i], template[i], isDeepEqual))\n return false;\n }\n return true;\n}\nfunction containsList(children, template) {\n if (template.length > children.length)\n return false;\n const cc = children.slice();\n const tt = template.slice();\n for (const t of tt) {\n let c = cc.shift();\n while (c) {\n if (matchesNode(c, t, false))\n break;\n c = cc.shift();\n }\n if (!c)\n return false;\n }\n return true;\n}\nfunction matchesNodeDeep(root, template, collectAll, isDeepEqual) {\n const results = [];\n const visit = (node, parent) => {\n if (matchesNode(node, template, isDeepEqual)) {\n const result = typeof node === "string" ? parent : node;\n if (result)\n results.push(result);\n return !collectAll;\n }\n if (typeof node === "string")\n return false;\n for (const child of node.children || []) {\n if (visit(child, node))\n return true;\n }\n return false;\n };\n visit(root, null);\n return results;\n}\nfunction buildByRefMap(root, map = /* @__PURE__ */ new Map()) {\n if (root == null ? void 0 : root.ref)\n map.set(root.ref, root);\n for (const child of (root == null ? void 0 : root.children) || []) {\n if (typeof child !== "string")\n buildByRefMap(child, map);\n }\n return map;\n}\nfunction compareSnapshots(ariaSnapshot, previousSnapshot) {\n var _a;\n const previousByRef = buildByRefMap(previousSnapshot == null ? void 0 : previousSnapshot.root);\n const result = /* @__PURE__ */ new Map();\n const visit = (ariaNode, previousNode) => {\n let same = ariaNode.children.length === (previousNode == null ? void 0 : previousNode.children.length) && ariaNodesEqual(ariaNode, previousNode);\n let canBeSkipped = same;\n for (let childIndex = 0; childIndex < ariaNode.children.length; childIndex++) {\n const child = ariaNode.children[childIndex];\n const previousChild = previousNode == null ? void 0 : previousNode.children[childIndex];\n if (typeof child === "string") {\n same && (same = child === previousChild);\n canBeSkipped && (canBeSkipped = child === previousChild);\n } else {\n let previous = typeof previousChild !== "string" ? previousChild : void 0;\n if (child.ref)\n previous = previousByRef.get(child.ref);\n const sameChild = visit(child, previous);\n if (!previous || !sameChild && !child.ref || previous !== previousChild)\n canBeSkipped = false;\n same && (same = sameChild && previous === previousChild);\n }\n }\n result.set(ariaNode, same ? "same" : canBeSkipped ? "skip" : "changed");\n return same;\n };\n visit(ariaSnapshot.root, previousByRef.get((_a = previousSnapshot == null ? void 0 : previousSnapshot.root) == null ? void 0 : _a.ref));\n return result;\n}\nfunction filterSnapshotDiff(nodes, statusMap) {\n const result = [];\n const visit = (ariaNode) => {\n const status = statusMap.get(ariaNode);\n if (status === "same") {\n } else if (status === "skip") {\n for (const child of ariaNode.children) {\n if (typeof child !== "string")\n visit(child);\n }\n } else {\n result.push(ariaNode);\n }\n };\n for (const node of nodes) {\n if (typeof node === "string")\n result.push(node);\n else\n visit(node);\n }\n return result;\n}\nfunction indent(depth) {\n return " ".repeat(depth);\n}\nfunction renderAriaTree(ariaSnapshot, publicOptions, previousSnapshot) {\n const options = toInternalOptions(publicOptions);\n const lines = [];\n const iframeDepths = {};\n const includeText = options.renderStringsAsRegex ? textContributesInfo : () => true;\n const renderString = options.renderStringsAsRegex ? convertToBestGuessRegex : (str) => str;\n let nodesToRender = ariaSnapshot.root.role === "fragment" ? ariaSnapshot.root.children : [ariaSnapshot.root];\n const statusMap = compareSnapshots(ariaSnapshot, previousSnapshot);\n if (previousSnapshot)\n nodesToRender = filterSnapshotDiff(nodesToRender, statusMap);\n const visitText = (text, depth) => {\n if (publicOptions.depth && depth > publicOptions.depth)\n return;\n const escaped = yamlEscapeValueIfNeeded(renderString(text));\n if (escaped)\n lines.push(indent(depth) + "- text: " + escaped);\n };\n const createKey = (ariaNode, renderCursorPointer) => {\n let key = ariaNode.role;\n if (ariaNode.name && ariaNode.name.length <= 900) {\n const name = renderString(ariaNode.name);\n if (name) {\n const stringifiedName = name.startsWith("/") && name.endsWith("/") ? name : JSON.stringify(name);\n key += " " + stringifiedName;\n }\n }\n if (ariaNode.checked === "mixed")\n key += ` [checked=mixed]`;\n if (ariaNode.checked === true)\n key += ` [checked]`;\n if (ariaNode.disabled)\n key += ` [disabled]`;\n if (ariaNode.expanded)\n key += ` [expanded]`;\n if (ariaNode.active && options.renderActive)\n key += ` [active]`;\n if (ariaNode.invalid === "grammar" || ariaNode.invalid === "spelling")\n key += ` [invalid=${ariaNode.invalid}]`;\n if (ariaNode.invalid === true)\n key += ` [invalid]`;\n if (ariaNode.level)\n key += ` [level=${ariaNode.level}]`;\n if (ariaNode.pressed === "mixed")\n key += ` [pressed=mixed]`;\n if (ariaNode.pressed === true)\n key += ` [pressed]`;\n if (ariaNode.selected === true)\n key += ` [selected]`;\n if (ariaNode.ref) {\n key += ` [ref=${ariaNode.ref}]`;\n if (renderCursorPointer && hasPointerCursor(ariaNode))\n key += " [cursor=pointer]";\n }\n if (options.renderBoxes) {\n const element = ariaNodeElement(ariaNode);\n if (element) {\n const r = element.getBoundingClientRect();\n key += ` [box=${Math.round(r.x)},${Math.round(r.y)},${Math.round(r.width)},${Math.round(r.height)}]`;\n }\n }\n return key;\n };\n const getSingleInlinedTextChild = (ariaNode) => {\n return (ariaNode == null ? void 0 : ariaNode.children.length) === 1 && typeof ariaNode.children[0] === "string" && !Object.keys(ariaNode.props).length ? ariaNode.children[0] : void 0;\n };\n const visit = (ariaNode, depth, renderCursorPointer) => {\n if (publicOptions.depth && depth > publicOptions.depth)\n return;\n if (ariaNode.role === "iframe" && ariaNode.ref)\n iframeDepths[ariaNode.ref] = depth;\n if (statusMap.get(ariaNode) === "same" && ariaNode.ref) {\n lines.push(indent(depth) + `- ref=${ariaNode.ref} [unchanged]`);\n return;\n }\n const isDiffRoot = !!previousSnapshot && !depth;\n const escapedKey = indent(depth) + "- " + (isDiffRoot ? " " : "") + yamlEscapeKeyIfNeeded(createKey(ariaNode, renderCursorPointer));\n const singleInlinedTextChild = getSingleInlinedTextChild(ariaNode);\n const isAtDepthLimit = !!publicOptions.depth && depth === publicOptions.depth;\n const hasNoChildren = !singleInlinedTextChild && (!ariaNode.children.length || isAtDepthLimit);\n if (hasNoChildren && !Object.keys(ariaNode.props).length) {\n lines.push(escapedKey);\n } else if (singleInlinedTextChild !== void 0) {\n const shouldInclude = includeText(ariaNode, singleInlinedTextChild);\n if (shouldInclude)\n lines.push(escapedKey + ": " + yamlEscapeValueIfNeeded(renderString(singleInlinedTextChild)));\n else\n lines.push(escapedKey);\n } else {\n lines.push(escapedKey + ":");\n for (const [name, value] of Object.entries(ariaNode.props))\n lines.push(indent(depth + 1) + "- /" + name + ": " + yamlEscapeValueIfNeeded(value));\n const inCursorPointer = !!ariaNode.ref && renderCursorPointer && hasPointerCursor(ariaNode);\n for (const child of ariaNode.children) {\n if (typeof child === "string")\n visitText(includeText(ariaNode, child) ? child : "", depth + 1);\n else\n visit(child, depth + 1, renderCursorPointer && !inCursorPointer);\n }\n }\n };\n for (const nodeToRender of nodesToRender) {\n if (typeof nodeToRender === "string")\n visitText(nodeToRender, 0);\n else\n visit(nodeToRender, 0, !!options.renderCursorPointer);\n }\n return { text: lines.join("\\n"), iframeDepths };\n}\nfunction convertToBestGuessRegex(text) {\n const dynamicContent = [\n // 550e8400-e29b-41d4-a716-446655440000\n { regex: /\\b[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}\\b/, replacement: "[0-9a-fA-F-]+" },\n // 2mb\n { regex: /\\b[\\d,.]+[bkmBKM]+\\b/, replacement: "[\\\\d,.]+[bkmBKM]+" },\n // 2ms, 20s\n { regex: /\\b\\d+[hmsp]+\\b/, replacement: "\\\\d+[hmsp]+" },\n { regex: /\\b[\\d,.]+[hmsp]+\\b/, replacement: "[\\\\d,.]+[hmsp]+" },\n // Do not replace single digits with regex by default.\n // 2+ digits: [Issue 22, 22.3, 2.33, 2,333]\n { regex: /\\b\\d+,\\d+\\b/, replacement: "\\\\d+,\\\\d+" },\n { regex: /\\b\\d+\\.\\d{2,}\\b/, replacement: "\\\\d+\\\\.\\\\d+" },\n { regex: /\\b\\d{2,}\\.\\d+\\b/, replacement: "\\\\d+\\\\.\\\\d+" },\n { regex: /\\b\\d{2,}\\b/, replacement: "\\\\d+" }\n ];\n let pattern = "";\n let lastIndex = 0;\n const combinedRegex = new RegExp(dynamicContent.map((r) => "(" + r.regex.source + ")").join("|"), "g");\n text.replace(combinedRegex, (match, ...args) => {\n const offset = args[args.length - 2];\n const groups = args.slice(0, -2);\n pattern += escapeRegExp(text.slice(lastIndex, offset));\n for (let i = 0; i < groups.length; i++) {\n if (groups[i]) {\n const { replacement } = dynamicContent[i];\n pattern += replacement;\n break;\n }\n }\n lastIndex = offset + match.length;\n return match;\n });\n if (!pattern)\n return text;\n pattern += escapeRegExp(text.slice(lastIndex));\n return String(new RegExp(pattern));\n}\nfunction textContributesInfo(node, text) {\n if (!text.length)\n return false;\n if (!node.name)\n return true;\n const substr = text.length <= 200 && node.name.length <= 200 ? longestCommonSubstring(text, node.name) : "";\n let filtered = text;\n while (substr && filtered.includes(substr))\n filtered = filtered.replace(substr, "");\n return filtered.trim().length / text.length > 0.1;\n}\nvar elementSymbol = Symbol("element");\nfunction ariaNodeElement(ariaNode) {\n return ariaNode[elementSymbol];\n}\nfunction setAriaNodeElement(ariaNode, element) {\n ariaNode[elementSymbol] = element;\n}\nfunction findNewElement(from, to) {\n const node = findNewNode(from, to);\n return node ? ariaNodeElement(node) : void 0;\n}\n\n// packages/injected/src/highlight.css?inline\nvar highlight_default = ":host{font-size:13px;font-family:system-ui,Ubuntu,Droid Sans,sans-serif;color:#333;color-scheme:light}svg{position:absolute;height:0}x-pw-tooltip{backdrop-filter:blur(5px);background-color:#fff;border-radius:6px;box-shadow:0 .5rem 1.2rem #0000004d;display:none;font-size:12.8px;font-weight:400;left:0;line-height:1.5;max-width:600px;position:absolute;top:0;padding:0;flex-direction:column;overflow:hidden}x-pw-tooltip-line{display:flex;max-width:600px;padding:6px;user-select:none;cursor:pointer}x-pw-tooltip-footer{display:flex;max-width:600px;padding:6px;user-select:none;color:#777}x-pw-dialog{background-color:#fff;pointer-events:auto;border-radius:6px;box-shadow:0 .5rem 1.2rem #0000004d;display:flex;flex-direction:column;position:absolute;z-index:10;font-size:13px}x-pw-dialog:not(.autosize){width:400px;height:150px}x-pw-dialog-body{display:flex;flex-direction:column;flex:auto}x-pw-dialog-body label{margin:5px 8px;display:flex;flex-direction:row;align-items:center}x-pw-highlight{position:absolute;top:0;left:0;width:0;height:0}x-pw-action-point{position:absolute;width:20px;height:20px;background:red;border-radius:10px;margin:-10px 0 0 -10px;z-index:2}x-pw-action-cursor{position:absolute;width:18px;height:22px;pointer-events:none;z-index:4;filter:drop-shadow(0 1px 2px rgba(0,0,0,.4))}x-pw-action-cursor svg{width:100%;height:100%;position:static}x-pw-title{position:absolute;backdrop-filter:blur(5px);background-color:#00000080;color:#fff;border-radius:6px;padding:6px;font-size:24px;line-height:1.4;white-space:nowrap;user-select:none;z-index:3}x-pw-user-overlays,x-pw-user-overlay{position:absolute;inset:0}@keyframes pw-fade-out{0%{opacity:1}to{opacity:0}}x-pw-separator{height:1px;margin:6px 9px;background:#949494e5}x-pw-tool-gripper{height:28px;width:24px;margin:2px 0;cursor:grab}x-pw-tool-gripper:active{cursor:grabbing}x-pw-tool-gripper>x-div{width:16px;height:16px;margin:6px 4px;clip-path:url(#icon-gripper);background-color:#555}x-pw-tools-list>label{display:flex;align-items:center;margin:0 10px;user-select:none}x-pw-tools-list{display:flex;width:100%;border-bottom:1px solid #dddddd}x-pw-tool-item{pointer-events:auto;height:28px;width:28px;border-radius:3px}x-pw-tool-item:not(.disabled){cursor:pointer}x-pw-tool-item:not(.disabled):hover{background-color:#dbdbdb}x-pw-tool-item.toggled{background-color:#8acae480}x-pw-tool-item.toggled:not(.disabled):hover{background-color:#8acae4c4}x-pw-tool-item>x-div{width:16px;height:16px;margin:6px;background-color:#3a3a3a}x-pw-tool-item.disabled>x-div{background-color:#61616180;cursor:default}x-pw-tool-item.record.toggled{background-color:transparent}x-pw-tool-item.record.toggled:not(.disabled):hover{background-color:#dbdbdb}x-pw-tool-item.record.toggled>x-div{background-color:#a1260d}x-pw-tool-item.record.disabled.toggled>x-div{opacity:.8}x-pw-tool-item.accept>x-div{background-color:#388a34}x-pw-tool-item.record>x-div{clip-path:url(#icon-circle-large-filled)}x-pw-tool-item.record.toggled>x-div{clip-path:url(#icon-stop-circle)}x-pw-tool-item.pick-locator>x-div{clip-path:url(#icon-inspect)}x-pw-tool-item.text>x-div{clip-path:url(#icon-whole-word)}x-pw-tool-item.visibility>x-div{clip-path:url(#icon-eye)}x-pw-tool-item.value>x-div{clip-path:url(#icon-symbol-constant)}x-pw-tool-item.snapshot>x-div{clip-path:url(#icon-gist)}x-pw-tool-item.accept>x-div{clip-path:url(#icon-check)}x-pw-tool-item.cancel>x-div{clip-path:url(#icon-close)}x-pw-tool-item.succeeded>x-div{clip-path:url(#icon-pass);background-color:#388a34!important}x-pw-overlay{position:absolute;top:0;max-width:min-content;z-index:2147483647;background:transparent;pointer-events:auto}x-pw-overlay x-pw-tools-list{background-color:#fffd;box-shadow:#0000001a 0 5px 5px;border-radius:3px;border-bottom:none}x-pw-overlay x-pw-tool-item{margin:2px}textarea.text-editor{font-family:system-ui,Ubuntu,Droid Sans,sans-serif;flex:auto;border:none;margin:6px 10px;color:#333;outline:1px solid transparent!important;resize:none;padding:0;font-size:13px}textarea.text-editor.does-not-match{outline:1px solid red!important}x-div{display:block}x-spacer{flex:auto}*{box-sizing:border-box}*[hidden]{display:none!important}x-locator-editor{flex:none;width:100%;height:60px;padding:4px;border-bottom:1px solid #dddddd;outline:1px solid transparent}x-locator-editor.does-not-match{outline:1px solid red}.CodeMirror{width:100%!important;height:100%!important}x-pw-action-list{flex:auto;display:flex;flex-direction:column;user-select:none}x-pw-action-item{padding:6px 10px;cursor:pointer;overflow:hidden}x-pw-action-item:hover{background-color:#f2f2f2}x-pw-action-item:last-child{border-bottom-left-radius:6px;border-bottom-right-radius:6px}\\n";\n\n// packages/injected/src/highlight.ts\nvar Highlight = class {\n constructor(injectedScript) {\n this._renderedEntries = [];\n this._userOverlays = /* @__PURE__ */ new Map();\n this._userOverlayHidden = false;\n this._language = "javascript";\n this._elementHighlightSelectors = /* @__PURE__ */ new Map();\n this._injectedScript = injectedScript;\n const document = injectedScript.document;\n this._isUnderTest = injectedScript.isUnderTest;\n this._glassPaneElement = document.createElement("x-pw-glass");\n this._glassPaneElement.setAttribute("popover", "manual");\n this._glassPaneElement.style.inset = "0";\n this._glassPaneElement.style.width = "100%";\n this._glassPaneElement.style.height = "100%";\n this._glassPaneElement.style.maxWidth = "none";\n this._glassPaneElement.style.maxHeight = "none";\n this._glassPaneElement.style.padding = "0";\n this._glassPaneElement.style.margin = "0";\n this._glassPaneElement.style.border = "none";\n this._glassPaneElement.style.overflow = "visible";\n this._glassPaneElement.style.pointerEvents = "none";\n this._glassPaneElement.style.display = "flex";\n this._glassPaneElement.style.backgroundColor = "transparent";\n this._actionPointElement = document.createElement("x-pw-action-point");\n this._actionPointElement.setAttribute("hidden", "true");\n this._actionCursorElement = document.createElement("x-pw-action-cursor");\n this._actionCursorElement.style.visibility = "hidden";\n this._actionCursorElement.appendChild(this._createCursorSvg(document));\n this._titleElement = document.createElement("x-pw-title");\n this._titleElement.setAttribute("hidden", "true");\n this._userOverlayContainer = document.createElement("x-pw-user-overlays");\n this._userOverlayContainer.setAttribute("hidden", "true");\n this._glassPaneShadow = this._glassPaneElement.attachShadow({ mode: this._isUnderTest ? "open" : "closed" });\n if (typeof this._glassPaneShadow.adoptedStyleSheets.push === "function") {\n const sheet = new this._injectedScript.window.CSSStyleSheet();\n sheet.replaceSync(highlight_default);\n this._glassPaneShadow.adoptedStyleSheets.push(sheet);\n } else {\n const styleElement = this._injectedScript.document.createElement("style");\n styleElement.textContent = highlight_default;\n this._glassPaneShadow.appendChild(styleElement);\n }\n this._glassPaneShadow.appendChild(this._actionPointElement);\n this._glassPaneShadow.appendChild(this._actionCursorElement);\n this._glassPaneShadow.appendChild(this._titleElement);\n this._glassPaneShadow.appendChild(this._userOverlayContainer);\n }\n install() {\n if (!this._injectedScript.document.documentElement)\n return;\n if (!this._injectedScript.document.documentElement.contains(this._glassPaneElement) || this._glassPaneElement.nextElementSibling)\n this._injectedScript.document.documentElement.appendChild(this._glassPaneElement);\n this._bringToFront();\n }\n _bringToFront() {\n this._glassPaneElement.hidePopover();\n this._glassPaneElement.showPopover();\n }\n setLanguage(language) {\n this._language = language;\n }\n addElementHighlight(selector, cssStyle) {\n const key = stringifySelector(selector);\n this._elementHighlightSelectors.set(key, { selector, cssStyle });\n this._ensureElementHighlightRaf();\n }\n removeElementHighlight(selector) {\n const key = stringifySelector(selector);\n if (!this._elementHighlightSelectors.delete(key))\n return;\n if (this._elementHighlightSelectors.size === 0) {\n if (this._rafRequest) {\n this._injectedScript.utils.builtins.cancelAnimationFrame(this._rafRequest);\n this._rafRequest = void 0;\n }\n this.clearHighlight();\n }\n }\n _ensureElementHighlightRaf() {\n if (this._rafRequest)\n return;\n const tick = () => {\n const entries = [];\n for (const { selector, cssStyle } of this._elementHighlightSelectors.values()) {\n const elements = this._injectedScript.querySelectorAll(selector, this._injectedScript.document.documentElement);\n const locator = asLocator(this._language, stringifySelector(selector));\n const color = elements.length > 1 ? "#f6b26b7f" : "#6fa8dc7f";\n for (let i = 0; i < elements.length; ++i) {\n const suffix = elements.length > 1 ? ` [${i + 1} of ${elements.length}]` : "";\n entries.push({ element: elements[i], color, tooltipText: locator + suffix, cssStyle });\n }\n }\n this.updateHighlight(entries);\n this._rafRequest = this._injectedScript.utils.builtins.requestAnimationFrame(tick);\n };\n this._rafRequest = this._injectedScript.utils.builtins.requestAnimationFrame(tick);\n }\n uninstall() {\n if (this._rafRequest) {\n this._injectedScript.utils.builtins.cancelAnimationFrame(this._rafRequest);\n this._rafRequest = void 0;\n }\n this._elementHighlightSelectors.clear();\n this._glassPaneElement.remove();\n }\n showActionPoint(x, y, fadeDuration) {\n this._actionPointElement.style.top = y + "px";\n this._actionPointElement.style.left = x + "px";\n this._actionPointElement.hidden = false;\n if (fadeDuration)\n this._actionPointElement.style.animation = `pw-fade-out ${fadeDuration}ms ease-out forwards`;\n else\n this._actionPointElement.style.animation = "";\n }\n hideActionPoint() {\n this._actionPointElement.hidden = true;\n }\n moveActionCursor(x, y, fadeDuration) {\n const moveDuration = fadeDuration ? Math.max(80, Math.min(fadeDuration * 0.6, 400)) : 0;\n this._actionCursorElement.style.transition = `top ${moveDuration}ms ease, left ${moveDuration}ms ease`;\n this._actionCursorElement.style.left = x + "px";\n this._actionCursorElement.style.top = y + "px";\n this._actionCursorElement.style.visibility = "visible";\n }\n hideActionCursor() {\n this._actionCursorElement.style.visibility = "hidden";\n }\n _createCursorSvg(document) {\n const svgNs = "http://www.w3.org/2000/svg";\n const svg = document.createElementNS(svgNs, "svg");\n svg.setAttribute("viewBox", "0 0 18 22");\n const path = document.createElementNS(svgNs, "path");\n path.setAttribute("d", "M1 1 L1 17 L5.5 13 L8 20.5 L11 19.5 L8.5 12 L15 12 Z");\n path.setAttribute("fill", "white");\n path.setAttribute("stroke", "black");\n path.setAttribute("stroke-width", "1.5");\n path.setAttribute("stroke-linejoin", "round");\n svg.appendChild(path);\n return svg;\n }\n showActionTitle(text, fadeDuration, position, fontSize) {\n this._titleElement.textContent = text;\n this._titleElement.hidden = false;\n if (fadeDuration) {\n const fadeTime = fadeDuration / 4;\n this._titleElement.style.animation = `pw-fade-out ${fadeTime}ms ease-out ${fadeDuration - fadeTime}ms forwards`;\n } else {\n this._titleElement.style.animation = "";\n }\n this._titleElement.style.top = "";\n this._titleElement.style.bottom = "";\n this._titleElement.style.left = "";\n this._titleElement.style.right = "";\n this._titleElement.style.transform = "";\n switch (position) {\n case "top-left":\n this._titleElement.style.top = "6px";\n this._titleElement.style.left = "6px";\n break;\n case "top":\n this._titleElement.style.top = "6px";\n this._titleElement.style.left = "50%";\n this._titleElement.style.transform = "translateX(-50%)";\n break;\n case "bottom-left":\n this._titleElement.style.bottom = "6px";\n this._titleElement.style.left = "6px";\n break;\n case "bottom":\n this._titleElement.style.bottom = "6px";\n this._titleElement.style.left = "50%";\n this._titleElement.style.transform = "translateX(-50%)";\n break;\n case "bottom-right":\n this._titleElement.style.bottom = "6px";\n this._titleElement.style.right = "6px";\n break;\n case "top-right":\n default:\n this._titleElement.style.top = "6px";\n this._titleElement.style.right = "6px";\n break;\n }\n if (fontSize)\n this._titleElement.style.fontSize = fontSize + "px";\n }\n hideActionTitle() {\n this._titleElement.hidden = true;\n }\n addUserOverlay(id, html) {\n const element = this._injectedScript.document.createElement("div");\n element.className = "x-pw-user-overlay";\n element.innerHTML = html;\n for (const script of element.querySelectorAll("script"))\n script.remove();\n for (const el of element.querySelectorAll("*")) {\n for (const attr of [...el.attributes]) {\n if (attr.name.startsWith("on"))\n el.removeAttribute(attr.name);\n }\n }\n this._userOverlays.set(id, element);\n this._userOverlayContainer.appendChild(element);\n this._userOverlayContainer.hidden = this._userOverlayHidden;\n return id;\n }\n getUserOverlay(id) {\n return this._userOverlays.get(id);\n }\n removeUserOverlay(id) {\n const element = this._userOverlays.get(id);\n if (element) {\n element.remove();\n this._userOverlays.delete(id);\n }\n if (this._userOverlays.size === 0)\n this._userOverlayContainer.hidden = true;\n }\n setUserOverlaysVisible(visible) {\n this._userOverlayHidden = !visible;\n this._userOverlayContainer.hidden = !visible || this._userOverlays.size === 0;\n }\n clearHighlight() {\n var _a, _b;\n for (const entry of this._renderedEntries) {\n (_a = entry.highlightElement) == null ? void 0 : _a.remove();\n (_b = entry.tooltipElement) == null ? void 0 : _b.remove();\n }\n this._renderedEntries = [];\n }\n maskElements(elements, color) {\n this.updateHighlight(elements.map((element) => ({ element, color })));\n }\n updateHighlight(entries) {\n if (this._highlightIsUpToDate(entries))\n return;\n this.clearHighlight();\n for (const entry of entries) {\n const highlightElement = this._createHighlightElement();\n this._glassPaneShadow.appendChild(highlightElement);\n let tooltipElement;\n if (entry.tooltipText) {\n tooltipElement = this._injectedScript.document.createElement("x-pw-tooltip");\n this._glassPaneShadow.appendChild(tooltipElement);\n tooltipElement.style.top = "0";\n tooltipElement.style.left = "0";\n tooltipElement.style.display = "flex";\n const lineElement = this._injectedScript.document.createElement("x-pw-tooltip-line");\n lineElement.textContent = entry.tooltipText;\n tooltipElement.appendChild(lineElement);\n }\n this._renderedEntries.push({ targetElement: entry.element, box: toDOMRect(entry.box), color: entry.color, borderColor: entry.borderColor, fadeDuration: entry.fadeDuration, cssStyle: entry.cssStyle, tooltipElement, highlightElement });\n }\n for (const entry of this._renderedEntries) {\n if (!entry.box && !entry.targetElement)\n continue;\n entry.box = entry.box || entry.targetElement.getBoundingClientRect();\n if (!entry.tooltipElement)\n continue;\n const { anchorLeft, anchorTop } = this.tooltipPosition(entry.box, entry.tooltipElement);\n entry.tooltipTop = anchorTop;\n entry.tooltipLeft = anchorLeft;\n }\n for (const entry of this._renderedEntries) {\n if (entry.tooltipElement) {\n entry.tooltipElement.style.top = entry.tooltipTop + "px";\n entry.tooltipElement.style.left = entry.tooltipLeft + "px";\n }\n const box = entry.box;\n entry.highlightElement.style.backgroundColor = entry.color;\n entry.highlightElement.style.left = box.x + "px";\n entry.highlightElement.style.top = box.y + "px";\n entry.highlightElement.style.width = box.width + "px";\n entry.highlightElement.style.height = box.height + "px";\n entry.highlightElement.style.display = "block";\n if (entry.borderColor)\n entry.highlightElement.style.border = "2px solid " + entry.borderColor;\n if (entry.fadeDuration)\n entry.highlightElement.style.animation = `pw-fade-out ${entry.fadeDuration}ms ease-out forwards`;\n if (entry.cssStyle)\n entry.highlightElement.style.cssText += ";" + entry.cssStyle;\n if (this._isUnderTest)\n console.error("Highlight box for test: " + JSON.stringify({ x: box.x, y: box.y, width: box.width, height: box.height }));\n }\n }\n firstBox() {\n var _a;\n return (_a = this._renderedEntries[0]) == null ? void 0 : _a.box;\n }\n firstTooltipBox() {\n const entry = this._renderedEntries[0];\n if (!entry || !entry.tooltipElement || entry.tooltipLeft === void 0 || entry.tooltipTop === void 0)\n return;\n return {\n x: entry.tooltipLeft,\n y: entry.tooltipTop,\n left: entry.tooltipLeft,\n top: entry.tooltipTop,\n width: entry.tooltipElement.offsetWidth,\n height: entry.tooltipElement.offsetHeight,\n bottom: entry.tooltipTop + entry.tooltipElement.offsetHeight,\n right: entry.tooltipLeft + entry.tooltipElement.offsetWidth,\n toJSON: () => {\n }\n };\n }\n // Note: there is a copy of this method in dialog.tsx. Please fix bugs in both places.\n tooltipPosition(box, tooltipElement) {\n const tooltipWidth = tooltipElement.offsetWidth;\n const tooltipHeight = tooltipElement.offsetHeight;\n const totalWidth = this._glassPaneElement.offsetWidth;\n const totalHeight = this._glassPaneElement.offsetHeight;\n let anchorLeft = Math.max(5, box.left);\n if (anchorLeft + tooltipWidth > totalWidth - 5)\n anchorLeft = totalWidth - tooltipWidth - 5;\n let anchorTop = Math.max(0, box.bottom) + 5;\n if (anchorTop + tooltipHeight > totalHeight - 5) {\n if (Math.max(0, box.top) > tooltipHeight + 5) {\n anchorTop = Math.max(0, box.top) - tooltipHeight - 5;\n } else {\n anchorTop = totalHeight - 5 - tooltipHeight;\n }\n }\n return { anchorLeft, anchorTop };\n }\n _highlightIsUpToDate(entries) {\n if (entries.length !== this._renderedEntries.length)\n return false;\n for (let i = 0; i < this._renderedEntries.length; ++i) {\n if (entries[i].element !== this._renderedEntries[i].targetElement)\n return false;\n if (entries[i].color !== this._renderedEntries[i].color)\n return false;\n if (entries[i].cssStyle !== this._renderedEntries[i].cssStyle)\n return false;\n const oldBox = this._renderedEntries[i].box;\n if (!oldBox)\n return false;\n const box = entries[i].box ? toDOMRect(entries[i].box) : entries[i].element.getBoundingClientRect();\n if (box.top !== oldBox.top || box.right !== oldBox.right || box.bottom !== oldBox.bottom || box.left !== oldBox.left)\n return false;\n }\n return true;\n }\n _createHighlightElement() {\n return this._injectedScript.document.createElement("x-pw-highlight");\n }\n appendChild(element) {\n this._glassPaneShadow.appendChild(element);\n }\n onGlassPaneClick(handler) {\n this._glassPaneElement.style.pointerEvents = "auto";\n this._glassPaneElement.style.backgroundColor = "rgba(0, 0, 0, 0.3)";\n this._glassPaneElement.addEventListener("click", handler);\n }\n offGlassPaneClick(handler) {\n this._glassPaneElement.style.pointerEvents = "none";\n this._glassPaneElement.style.backgroundColor = "transparent";\n this._glassPaneElement.removeEventListener("click", handler);\n }\n};\nfunction toDOMRect(box) {\n if (!box)\n return void 0;\n return new DOMRect(box.x, box.y, box.width, box.height);\n}\n\n// packages/injected/src/layoutSelectorUtils.ts\nfunction boxRightOf(box1, box2, maxDistance) {\n const distance = box1.left - box2.right;\n if (distance < 0 || maxDistance !== void 0 && distance > maxDistance)\n return;\n return distance + Math.max(box2.bottom - box1.bottom, 0) + Math.max(box1.top - box2.top, 0);\n}\nfunction boxLeftOf(box1, box2, maxDistance) {\n const distance = box2.left - box1.right;\n if (distance < 0 || maxDistance !== void 0 && distance > maxDistance)\n return;\n return distance + Math.max(box2.bottom - box1.bottom, 0) + Math.max(box1.top - box2.top, 0);\n}\nfunction boxAbove(box1, box2, maxDistance) {\n const distance = box2.top - box1.bottom;\n if (distance < 0 || maxDistance !== void 0 && distance > maxDistance)\n return;\n return distance + Math.max(box1.left - box2.left, 0) + Math.max(box2.right - box1.right, 0);\n}\nfunction boxBelow(box1, box2, maxDistance) {\n const distance = box1.top - box2.bottom;\n if (distance < 0 || maxDistance !== void 0 && distance > maxDistance)\n return;\n return distance + Math.max(box1.left - box2.left, 0) + Math.max(box2.right - box1.right, 0);\n}\nfunction boxNear(box1, box2, maxDistance) {\n const kThreshold = maxDistance === void 0 ? 50 : maxDistance;\n let score = 0;\n if (box1.left - box2.right >= 0)\n score += box1.left - box2.right;\n if (box2.left - box1.right >= 0)\n score += box2.left - box1.right;\n if (box2.top - box1.bottom >= 0)\n score += box2.top - box1.bottom;\n if (box1.top - box2.bottom >= 0)\n score += box1.top - box2.bottom;\n return score > kThreshold ? void 0 : score;\n}\nvar kLayoutSelectorNames = ["left-of", "right-of", "above", "below", "near"];\nfunction layoutSelectorScore(name, element, inner, maxDistance) {\n const box = element.getBoundingClientRect();\n const scorer = { "left-of": boxLeftOf, "right-of": boxRightOf, "above": boxAbove, "below": boxBelow, "near": boxNear }[name];\n let bestScore;\n for (const e of inner) {\n if (e === element)\n continue;\n const score = scorer(box, e.getBoundingClientRect(), maxDistance);\n if (score === void 0)\n continue;\n if (bestScore === void 0 || score < bestScore)\n bestScore = score;\n }\n return bestScore;\n}\n\n// packages/injected/src/selectorUtils.ts\nfunction matchesAttributePart(value, attr) {\n const objValue = typeof value === "string" && !attr.caseSensitive ? value.toUpperCase() : value;\n const attrValue = typeof attr.value === "string" && !attr.caseSensitive ? attr.value.toUpperCase() : attr.value;\n if (attr.op === "")\n return !!objValue;\n if (attr.op === "=") {\n if (attrValue instanceof RegExp)\n return typeof objValue === "string" && !!objValue.match(attrValue);\n return objValue === attrValue;\n }\n if (typeof objValue !== "string" || typeof attrValue !== "string")\n return false;\n if (attr.op === "*=")\n return objValue.includes(attrValue);\n if (attr.op === "^=")\n return objValue.startsWith(attrValue);\n if (attr.op === "$=")\n return objValue.endsWith(attrValue);\n if (attr.op === "|=")\n return objValue === attrValue || objValue.startsWith(attrValue + "-");\n if (attr.op === "~=")\n return objValue.split(" ").includes(attrValue);\n return false;\n}\nfunction shouldSkipForTextMatching(element) {\n const document = element.ownerDocument;\n return element.nodeName === "SCRIPT" || element.nodeName === "NOSCRIPT" || element.nodeName === "STYLE" || document.head && document.head.contains(element);\n}\nfunction elementText(cache, root) {\n let value = cache.get(root);\n if (value === void 0) {\n value = { full: "", normalized: "", immediate: [] };\n if (!shouldSkipForTextMatching(root)) {\n let currentImmediate = "";\n if (root instanceof HTMLInputElement && (root.type === "submit" || root.type === "button")) {\n value = { full: root.value, normalized: normalizeWhiteSpace(root.value), immediate: [root.value] };\n } else {\n for (let child = root.firstChild; child; child = child.nextSibling) {\n if (child.nodeType === Node.TEXT_NODE) {\n value.full += child.nodeValue || "";\n currentImmediate += child.nodeValue || "";\n } else if (child.nodeType === Node.COMMENT_NODE) {\n continue;\n } else {\n if (currentImmediate)\n value.immediate.push(currentImmediate);\n currentImmediate = "";\n if (child.nodeType === Node.ELEMENT_NODE)\n value.full += elementText(cache, child).full;\n }\n }\n if (currentImmediate)\n value.immediate.push(currentImmediate);\n if (root.shadowRoot)\n value.full += elementText(cache, root.shadowRoot).full;\n if (value.full)\n value.normalized = normalizeWhiteSpace(value.full);\n }\n }\n cache.set(root, value);\n }\n return value;\n}\nfunction elementMatchesText(cache, element, matcher) {\n if (shouldSkipForTextMatching(element))\n return "none";\n if (!matcher(elementText(cache, element)))\n return "none";\n for (let child = element.firstChild; child; child = child.nextSibling) {\n if (child.nodeType === Node.ELEMENT_NODE && matcher(elementText(cache, child)))\n return "selfAndChildren";\n }\n if (element.shadowRoot && matcher(elementText(cache, element.shadowRoot)))\n return "selfAndChildren";\n return "self";\n}\nfunction getElementLabels(textCache, element) {\n const labels = getAriaLabelledByElements(element);\n if (labels)\n return labels.map((label) => elementText(textCache, label));\n const ariaLabel = element.getAttribute("aria-label");\n if (ariaLabel !== null && !!ariaLabel.trim())\n return [{ full: ariaLabel, normalized: normalizeWhiteSpace(ariaLabel), immediate: [ariaLabel] }];\n const isNonHiddenInput = element.nodeName === "INPUT" && element.type !== "hidden";\n if (["BUTTON", "METER", "OUTPUT", "PROGRESS", "SELECT", "TEXTAREA"].includes(element.nodeName) || isNonHiddenInput) {\n const labels2 = element.labels;\n if (labels2)\n return [...labels2].map((label) => elementText(textCache, label));\n }\n return [];\n}\n\n// packages/injected/src/roleSelectorEngine.ts\nvar kSupportedAttributes = ["selected", "checked", "pressed", "expanded", "level", "disabled", "name", "description", "include-hidden"];\nkSupportedAttributes.sort();\nfunction validateSupportedRole(attr, roles, role) {\n if (!roles.includes(role))\n throw new Error(`"${attr}" attribute is only supported for roles: ${roles.slice().sort().map((role2) => `"${role2}"`).join(", ")}`);\n}\nfunction validateSupportedValues(attr, values) {\n if (attr.op !== "" && !values.includes(attr.value))\n throw new Error(`"${attr.name}" must be one of ${values.map((v) => JSON.stringify(v)).join(", ")}`);\n}\nfunction validateSupportedOp(attr, ops) {\n if (!ops.includes(attr.op))\n throw new Error(`"${attr.name}" does not support "${attr.op}" matcher`);\n}\nfunction validateAttributes(attrs, role) {\n const options = { role };\n for (const attr of attrs) {\n switch (attr.name) {\n case "checked": {\n validateSupportedRole(attr.name, kAriaCheckedRoles, role);\n validateSupportedValues(attr, [true, false, "mixed"]);\n validateSupportedOp(attr, ["", "="]);\n options.checked = attr.op === "" ? true : attr.value;\n break;\n }\n case "pressed": {\n validateSupportedRole(attr.name, kAriaPressedRoles, role);\n validateSupportedValues(attr, [true, false, "mixed"]);\n validateSupportedOp(attr, ["", "="]);\n options.pressed = attr.op === "" ? true : attr.value;\n break;\n }\n case "selected": {\n validateSupportedRole(attr.name, kAriaSelectedRoles, role);\n validateSupportedValues(attr, [true, false]);\n validateSupportedOp(attr, ["", "="]);\n options.selected = attr.op === "" ? true : attr.value;\n break;\n }\n case "expanded": {\n validateSupportedRole(attr.name, kAriaExpandedRoles, role);\n validateSupportedValues(attr, [true, false]);\n validateSupportedOp(attr, ["", "="]);\n options.expanded = attr.op === "" ? true : attr.value;\n break;\n }\n case "level": {\n validateSupportedRole(attr.name, kAriaLevelRoles, role);\n if (typeof attr.value === "string")\n attr.value = +attr.value;\n if (attr.op !== "=" || typeof attr.value !== "number" || Number.isNaN(attr.value))\n throw new Error(`"level" attribute must be compared to a number`);\n options.level = attr.value;\n break;\n }\n case "disabled": {\n validateSupportedValues(attr, [true, false]);\n validateSupportedOp(attr, ["", "="]);\n options.disabled = attr.op === "" ? true : attr.value;\n break;\n }\n case "name": {\n if (attr.op === "")\n throw new Error(`"name" attribute must have a value`);\n if (typeof attr.value !== "string" && !(attr.value instanceof RegExp))\n throw new Error(`"name" attribute must be a string or a regular expression`);\n options.name = attr.value;\n options.nameOp = attr.op;\n options.nameExact = attr.caseSensitive;\n break;\n }\n case "description": {\n if (attr.op === "")\n throw new Error(`"description" attribute must have a value`);\n if (typeof attr.value !== "string" && !(attr.value instanceof RegExp))\n throw new Error(`"description" attribute must be a string or a regular expression`);\n options.description = attr.value;\n options.descriptionOp = attr.op;\n options.descriptionExact = attr.caseSensitive;\n break;\n }\n case "include-hidden": {\n validateSupportedValues(attr, [true, false]);\n validateSupportedOp(attr, ["", "="]);\n options.includeHidden = attr.op === "" ? true : attr.value;\n break;\n }\n default: {\n throw new Error(`Unknown attribute "${attr.name}", must be one of ${kSupportedAttributes.map((a) => `"${a}"`).join(", ")}.`);\n }\n }\n }\n return options;\n}\nfunction queryRole(scope, options, internal) {\n const result = [];\n const match = (element) => {\n if (getAriaRole(element) !== options.role)\n return;\n if (options.selected !== void 0 && getAriaSelected(element) !== options.selected)\n return;\n if (options.checked !== void 0 && getAriaChecked(element) !== options.checked)\n return;\n if (options.pressed !== void 0 && getAriaPressed(element) !== options.pressed)\n return;\n if (options.expanded !== void 0 && getAriaExpanded(element) !== options.expanded)\n return;\n if (options.level !== void 0 && getAriaLevel(element) !== options.level)\n return;\n if (options.disabled !== void 0 && getAriaDisabled(element) !== options.disabled)\n return;\n if (!options.includeHidden) {\n const isHidden = isElementHiddenForAria(element);\n if (isHidden)\n return;\n }\n if (options.name !== void 0) {\n const accessibleName = normalizeWhiteSpace(getElementAccessibleName(element, !!options.includeHidden));\n if (typeof options.name === "string")\n options.name = normalizeWhiteSpace(options.name);\n if (internal && !options.nameExact && options.nameOp === "=")\n options.nameOp = "*=";\n if (!matchesAttributePart(accessibleName, { name: "", jsonPath: [], op: options.nameOp || "=", value: options.name, caseSensitive: !!options.nameExact }))\n return;\n }\n if (options.description !== void 0) {\n const accessibleDescription = normalizeWhiteSpace(getElementAccessibleDescription(element, !!options.includeHidden));\n if (typeof options.description === "string")\n options.description = normalizeWhiteSpace(options.description);\n if (internal && !options.descriptionExact && options.descriptionOp === "=")\n options.descriptionOp = "*=";\n if (!matchesAttributePart(accessibleDescription, { name: "", jsonPath: [], op: options.descriptionOp || "=", value: options.description, caseSensitive: !!options.descriptionExact }))\n return;\n }\n result.push(element);\n };\n const query = (root) => {\n const shadows = [];\n if (root.shadowRoot)\n shadows.push(root.shadowRoot);\n for (const element of root.querySelectorAll("*")) {\n match(element);\n if (element.shadowRoot)\n shadows.push(element.shadowRoot);\n }\n shadows.forEach(query);\n };\n query(scope);\n return result;\n}\nfunction createRoleEngine(internal) {\n return {\n queryAll: (scope, selector) => {\n const parsed = parseAttributeSelector(selector, true);\n const role = parsed.name.toLowerCase();\n if (!role)\n throw new Error(`Role must not be empty`);\n const options = validateAttributes(parsed.attributes, role);\n beginAriaCaches();\n try {\n return queryRole(scope, options, internal);\n } finally {\n endAriaCaches();\n }\n }\n };\n}\n\n// packages/injected/src/selectorEvaluator.ts\nvar SelectorEvaluatorImpl = class {\n constructor() {\n this._retainCacheCounter = 0;\n this._cacheText = /* @__PURE__ */ new Map();\n this._cacheQueryCSS = /* @__PURE__ */ new Map();\n this._cacheMatches = /* @__PURE__ */ new Map();\n this._cacheQuery = /* @__PURE__ */ new Map();\n this._cacheMatchesSimple = /* @__PURE__ */ new Map();\n this._cacheMatchesParents = /* @__PURE__ */ new Map();\n this._cacheCallMatches = /* @__PURE__ */ new Map();\n this._cacheCallQuery = /* @__PURE__ */ new Map();\n this._cacheQuerySimple = /* @__PURE__ */ new Map();\n this._engines = /* @__PURE__ */ new Map();\n this._engines.set("not", notEngine);\n this._engines.set("is", isEngine);\n this._engines.set("where", isEngine);\n this._engines.set("has", hasEngine);\n this._engines.set("scope", scopeEngine);\n this._engines.set("light", lightEngine);\n this._engines.set("visible", visibleEngine);\n this._engines.set("text", textEngine);\n this._engines.set("text-is", textIsEngine);\n this._engines.set("text-matches", textMatchesEngine);\n this._engines.set("has-text", hasTextEngine);\n this._engines.set("right-of", createLayoutEngine("right-of"));\n this._engines.set("left-of", createLayoutEngine("left-of"));\n this._engines.set("above", createLayoutEngine("above"));\n this._engines.set("below", createLayoutEngine("below"));\n this._engines.set("near", createLayoutEngine("near"));\n this._engines.set("nth-match", nthMatchEngine);\n const allNames = [...this._engines.keys()];\n allNames.sort();\n const parserNames = [...customCSSNames];\n parserNames.sort();\n if (allNames.join("|") !== parserNames.join("|"))\n throw new Error(`Please keep customCSSNames in sync with evaluator engines: ${allNames.join("|")} vs ${parserNames.join("|")}`);\n }\n begin() {\n ++this._retainCacheCounter;\n }\n end() {\n --this._retainCacheCounter;\n if (!this._retainCacheCounter) {\n this._cacheQueryCSS.clear();\n this._cacheMatches.clear();\n this._cacheQuery.clear();\n this._cacheMatchesSimple.clear();\n this._cacheMatchesParents.clear();\n this._cacheCallMatches.clear();\n this._cacheCallQuery.clear();\n this._cacheQuerySimple.clear();\n this._cacheText.clear();\n }\n }\n _cached(cache, main, rest, cb) {\n if (!cache.has(main))\n cache.set(main, []);\n const entries = cache.get(main);\n const entry = entries.find((e) => rest.every((value, index) => e.rest[index] === value));\n if (entry)\n return entry.result;\n const result = cb();\n entries.push({ rest, result });\n return result;\n }\n _checkSelector(s) {\n const wellFormed = typeof s === "object" && s && (Array.isArray(s) || "simples" in s && s.simples.length);\n if (!wellFormed)\n throw new Error(`Malformed selector "${s}"`);\n return s;\n }\n matches(element, s, context) {\n const selector = this._checkSelector(s);\n this.begin();\n try {\n return this._cached(this._cacheMatches, element, [selector, context.scope, context.pierceShadow, context.originalScope], () => {\n if (Array.isArray(selector))\n return this._matchesEngine(isEngine, element, selector, context);\n if (this._hasScopeClause(selector))\n context = this._expandContextForScopeMatching(context);\n if (!this._matchesSimple(element, selector.simples[selector.simples.length - 1].selector, context))\n return false;\n return this._matchesParents(element, selector, selector.simples.length - 2, context);\n });\n } finally {\n this.end();\n }\n }\n query(context, s) {\n const selector = this._checkSelector(s);\n this.begin();\n try {\n return this._cached(this._cacheQuery, selector, [context.scope, context.pierceShadow, context.originalScope], () => {\n if (Array.isArray(selector))\n return this._queryEngine(isEngine, context, selector);\n if (this._hasScopeClause(selector))\n context = this._expandContextForScopeMatching(context);\n const previousScoreMap = this._scoreMap;\n this._scoreMap = /* @__PURE__ */ new Map();\n let elements = this._querySimple(context, selector.simples[selector.simples.length - 1].selector);\n elements = elements.filter((element) => this._matchesParents(element, selector, selector.simples.length - 2, context));\n if (this._scoreMap.size) {\n elements.sort((a, b) => {\n const aScore = this._scoreMap.get(a);\n const bScore = this._scoreMap.get(b);\n if (aScore === bScore)\n return 0;\n if (aScore === void 0)\n return 1;\n if (bScore === void 0)\n return -1;\n return aScore - bScore;\n });\n }\n this._scoreMap = previousScoreMap;\n return elements;\n });\n } finally {\n this.end();\n }\n }\n _markScore(element, score) {\n if (this._scoreMap)\n this._scoreMap.set(element, score);\n }\n _hasScopeClause(selector) {\n return selector.simples.some((simple) => simple.selector.functions.some((f) => f.name === "scope"));\n }\n _expandContextForScopeMatching(context) {\n if (context.scope.nodeType !== 1)\n return context;\n const scope = parentElementOrShadowHost(context.scope);\n if (!scope)\n return context;\n return { ...context, scope, originalScope: context.originalScope || context.scope };\n }\n _matchesSimple(element, simple, context) {\n return this._cached(this._cacheMatchesSimple, element, [simple, context.scope, context.pierceShadow, context.originalScope], () => {\n if (element === context.scope)\n return false;\n if (simple.css && !this._matchesCSS(element, simple.css))\n return false;\n for (const func of simple.functions) {\n if (!this._matchesEngine(this._getEngine(func.name), element, func.args, context))\n return false;\n }\n return true;\n });\n }\n _querySimple(context, simple) {\n if (!simple.functions.length)\n return this._queryCSS(context, simple.css || "*");\n return this._cached(this._cacheQuerySimple, simple, [context.scope, context.pierceShadow, context.originalScope], () => {\n let css = simple.css;\n const funcs = simple.functions;\n if (css === "*" && funcs.length)\n css = void 0;\n let elements;\n let firstIndex = -1;\n if (css !== void 0) {\n elements = this._queryCSS(context, css);\n } else {\n firstIndex = funcs.findIndex((func) => this._getEngine(func.name).query !== void 0);\n if (firstIndex === -1)\n firstIndex = 0;\n elements = this._queryEngine(this._getEngine(funcs[firstIndex].name), context, funcs[firstIndex].args);\n }\n for (let i = 0; i < funcs.length; i++) {\n if (i === firstIndex)\n continue;\n const engine = this._getEngine(funcs[i].name);\n if (engine.matches !== void 0)\n elements = elements.filter((e) => this._matchesEngine(engine, e, funcs[i].args, context));\n }\n for (let i = 0; i < funcs.length; i++) {\n if (i === firstIndex)\n continue;\n const engine = this._getEngine(funcs[i].name);\n if (engine.matches === void 0)\n elements = elements.filter((e) => this._matchesEngine(engine, e, funcs[i].args, context));\n }\n return elements;\n });\n }\n _matchesParents(element, complex, index, context) {\n if (index < 0)\n return true;\n return this._cached(this._cacheMatchesParents, element, [complex, index, context.scope, context.pierceShadow, context.originalScope], () => {\n const { selector: simple, combinator } = complex.simples[index];\n if (combinator === ">") {\n const parent = parentElementOrShadowHostInContext(element, context);\n if (!parent || !this._matchesSimple(parent, simple, context))\n return false;\n return this._matchesParents(parent, complex, index - 1, context);\n }\n if (combinator === "+") {\n const previousSibling = previousSiblingInContext(element, context);\n if (!previousSibling || !this._matchesSimple(previousSibling, simple, context))\n return false;\n return this._matchesParents(previousSibling, complex, index - 1, context);\n }\n if (combinator === "") {\n let parent = parentElementOrShadowHostInContext(element, context);\n while (parent) {\n if (this._matchesSimple(parent, simple, context)) {\n if (this._matchesParents(parent, complex, index - 1, context))\n return true;\n if (complex.simples[index - 1].combinator === "")\n break;\n }\n parent = parentElementOrShadowHostInContext(parent, context);\n }\n return false;\n }\n if (combinator === "~") {\n let previousSibling = previousSiblingInContext(element, context);\n while (previousSibling) {\n if (this._matchesSimple(previousSibling, simple, context)) {\n if (this._matchesParents(previousSibling, complex, index - 1, context))\n return true;\n if (complex.simples[index - 1].combinator === "~")\n break;\n }\n previousSibling = previousSiblingInContext(previousSibling, context);\n }\n return false;\n }\n if (combinator === ">=") {\n let parent = element;\n while (parent) {\n if (this._matchesSimple(parent, simple, context)) {\n if (this._matchesParents(parent, complex, index - 1, context))\n return true;\n if (complex.simples[index - 1].combinator === "")\n break;\n }\n parent = parentElementOrShadowHostInContext(parent, context);\n }\n return false;\n }\n throw new Error(`Unsupported combinator "${combinator}"`);\n });\n }\n _matchesEngine(engine, element, args, context) {\n if (engine.matches)\n return this._callMatches(engine, element, args, context);\n if (engine.query)\n return this._callQuery(engine, args, context).includes(element);\n throw new Error(`Selector engine should implement "matches" or "query"`);\n }\n _queryEngine(engine, context, args) {\n if (engine.query)\n return this._callQuery(engine, args, context);\n if (engine.matches)\n return this._queryCSS(context, "*").filter((element) => this._callMatches(engine, element, args, context));\n throw new Error(`Selector engine should implement "matches" or "query"`);\n }\n _callMatches(engine, element, args, context) {\n return this._cached(this._cacheCallMatches, element, [engine, context.scope, context.pierceShadow, context.originalScope, ...args], () => {\n return engine.matches(element, args, context, this);\n });\n }\n _callQuery(engine, args, context) {\n return this._cached(this._cacheCallQuery, engine, [context.scope, context.pierceShadow, context.originalScope, ...args], () => {\n return engine.query(context, args, this);\n });\n }\n _matchesCSS(element, css) {\n return element.matches(css);\n }\n _queryCSS(context, css) {\n return this._cached(this._cacheQueryCSS, css, [context.scope, context.pierceShadow, context.originalScope], () => {\n let result = [];\n function query(root) {\n result = result.concat([...root.querySelectorAll(css)]);\n if (!context.pierceShadow)\n return;\n if (root.shadowRoot)\n query(root.shadowRoot);\n for (const element of root.querySelectorAll("*")) {\n if (element.shadowRoot)\n query(element.shadowRoot);\n }\n }\n query(context.scope);\n return result;\n });\n }\n _getEngine(name) {\n const engine = this._engines.get(name);\n if (!engine)\n throw new Error(`Unknown selector engine "${name}"`);\n return engine;\n }\n};\nvar isEngine = {\n matches(element, args, context, evaluator) {\n if (args.length === 0)\n throw new Error(`"is" engine expects non-empty selector list`);\n return args.some((selector) => evaluator.matches(element, selector, context));\n },\n query(context, args, evaluator) {\n if (args.length === 0)\n throw new Error(`"is" engine expects non-empty selector list`);\n let elements = [];\n for (const arg of args)\n elements = elements.concat(evaluator.query(context, arg));\n return args.length === 1 ? elements : sortInDOMOrder(elements);\n }\n};\nvar hasEngine = {\n matches(element, args, context, evaluator) {\n if (args.length === 0)\n throw new Error(`"has" engine expects non-empty selector list`);\n return evaluator.query({ ...context, scope: element }, args).length > 0;\n }\n // TODO: we can implement efficient "query" by matching "args" and returning\n // all parents/descendants, just have to be careful with the ":scope" matching.\n};\nvar scopeEngine = {\n matches(element, args, context, evaluator) {\n if (args.length !== 0)\n throw new Error(`"scope" engine expects no arguments`);\n const actualScope = context.originalScope || context.scope;\n if (actualScope.nodeType === 9)\n return element === actualScope.documentElement;\n return element === actualScope;\n },\n query(context, args, evaluator) {\n if (args.length !== 0)\n throw new Error(`"scope" engine expects no arguments`);\n const actualScope = context.originalScope || context.scope;\n if (actualScope.nodeType === 9) {\n const root = actualScope.documentElement;\n return root ? [root] : [];\n }\n if (actualScope.nodeType === 1)\n return [actualScope];\n return [];\n }\n};\nvar notEngine = {\n matches(element, args, context, evaluator) {\n if (args.length === 0)\n throw new Error(`"not" engine expects non-empty selector list`);\n return !evaluator.matches(element, args, context);\n }\n};\nvar lightEngine = {\n query(context, args, evaluator) {\n return evaluator.query({ ...context, pierceShadow: false }, args);\n },\n matches(element, args, context, evaluator) {\n return evaluator.matches(element, args, { ...context, pierceShadow: false });\n }\n};\nvar visibleEngine = {\n matches(element, args, context, evaluator) {\n if (args.length)\n throw new Error(`"visible" engine expects no arguments`);\n return isElementVisible(element);\n }\n};\nvar textEngine = {\n matches(element, args, context, evaluator) {\n if (args.length !== 1 || typeof args[0] !== "string")\n throw new Error(`"text" engine expects a single string`);\n const text = normalizeWhiteSpace(args[0]).toLowerCase();\n const matcher = (elementText2) => elementText2.normalized.toLowerCase().includes(text);\n return elementMatchesText(evaluator._cacheText, element, matcher) === "self";\n }\n};\nvar textIsEngine = {\n matches(element, args, context, evaluator) {\n if (args.length !== 1 || typeof args[0] !== "string")\n throw new Error(`"text-is" engine expects a single string`);\n const text = normalizeWhiteSpace(args[0]);\n const matcher = (elementText2) => {\n if (!text && !elementText2.immediate.length)\n return true;\n return elementText2.immediate.some((s) => normalizeWhiteSpace(s) === text);\n };\n return elementMatchesText(evaluator._cacheText, element, matcher) !== "none";\n }\n};\nvar textMatchesEngine = {\n matches(element, args, context, evaluator) {\n if (args.length === 0 || typeof args[0] !== "string" || args.length > 2 || args.length === 2 && typeof args[1] !== "string")\n throw new Error(`"text-matches" engine expects a regexp body and optional regexp flags`);\n const re = new RegExp(args[0], args.length === 2 ? args[1] : void 0);\n const matcher = (elementText2) => re.test(elementText2.full);\n return elementMatchesText(evaluator._cacheText, element, matcher) === "self";\n }\n};\nvar hasTextEngine = {\n matches(element, args, context, evaluator) {\n if (args.length !== 1 || typeof args[0] !== "string")\n throw new Error(`"has-text" engine expects a single string`);\n if (shouldSkipForTextMatching(element))\n return false;\n const text = normalizeWhiteSpace(args[0]).toLowerCase();\n const matcher = (elementText2) => elementText2.normalized.toLowerCase().includes(text);\n return matcher(elementText(evaluator._cacheText, element));\n }\n};\nfunction createLayoutEngine(name) {\n return {\n matches(element, args, context, evaluator) {\n const maxDistance = args.length && typeof args[args.length - 1] === "number" ? args[args.length - 1] : void 0;\n const queryArgs = maxDistance === void 0 ? args : args.slice(0, args.length - 1);\n if (args.length < 1 + (maxDistance === void 0 ? 0 : 1))\n throw new Error(`"${name}" engine expects a selector list and optional maximum distance in pixels`);\n const inner = evaluator.query(context, queryArgs);\n const score = layoutSelectorScore(name, element, inner, maxDistance);\n if (score === void 0)\n return false;\n evaluator._markScore(element, score);\n return true;\n }\n };\n}\nvar nthMatchEngine = {\n query(context, args, evaluator) {\n let index = args[args.length - 1];\n if (args.length < 2)\n throw new Error(`"nth-match" engine expects non-empty selector list and an index argument`);\n if (typeof index !== "number" || index < 1)\n throw new Error(`"nth-match" engine expects a one-based index as the last argument`);\n const elements = isEngine.query(context, args.slice(0, args.length - 1), evaluator);\n index--;\n return index < elements.length ? [elements[index]] : [];\n }\n};\nfunction parentElementOrShadowHostInContext(element, context) {\n if (element === context.scope)\n return;\n if (!context.pierceShadow)\n return element.parentElement || void 0;\n return parentElementOrShadowHost(element);\n}\nfunction previousSiblingInContext(element, context) {\n if (element === context.scope)\n return;\n return element.previousElementSibling || void 0;\n}\nfunction sortInDOMOrder(elements) {\n const elementToEntry = /* @__PURE__ */ new Map();\n const roots = [];\n const result = [];\n function append(element) {\n let entry = elementToEntry.get(element);\n if (entry)\n return entry;\n const parent = parentElementOrShadowHost(element);\n if (parent) {\n const parentEntry = append(parent);\n parentEntry.children.push(element);\n } else {\n roots.push(element);\n }\n entry = { children: [], taken: false };\n elementToEntry.set(element, entry);\n return entry;\n }\n for (const e of elements)\n append(e).taken = true;\n function visit(element) {\n const entry = elementToEntry.get(element);\n if (entry.taken)\n result.push(element);\n if (entry.children.length > 1) {\n const set = new Set(entry.children);\n entry.children = [];\n let child = element.firstElementChild;\n while (child && entry.children.length < set.size) {\n if (set.has(child))\n entry.children.push(child);\n child = child.nextElementSibling;\n }\n child = element.shadowRoot ? element.shadowRoot.firstElementChild : null;\n while (child && entry.children.length < set.size) {\n if (set.has(child))\n entry.children.push(child);\n child = child.nextElementSibling;\n }\n }\n entry.children.forEach(visit);\n }\n roots.forEach(visit);\n return result;\n}\n\n// packages/injected/src/selectorGenerator.ts\nvar kTextScoreRange = 10;\nvar kExactPenalty = kTextScoreRange / 2;\nvar kTestIdScore = 1;\nvar kOtherTestIdScore = 2;\nvar kIframeByAttributeScore = 10;\nvar kBeginPenalizedScore = 50;\nvar kRoleWithNameScore = 100;\nvar kPlaceholderScore = 120;\nvar kLabelScore = 140;\nvar kAltTextScore = 160;\nvar kTextScore = 180;\nvar kTitleScore = 200;\nvar kTextScoreRegex = 250;\nvar kPlaceholderScoreExact = kPlaceholderScore + kExactPenalty;\nvar kLabelScoreExact = kLabelScore + kExactPenalty;\nvar kRoleWithNameScoreExact = kRoleWithNameScore + kExactPenalty;\nvar kAltTextScoreExact = kAltTextScore + kExactPenalty;\nvar kTextScoreExact = kTextScore + kExactPenalty;\nvar kTitleScoreExact = kTitleScore + kExactPenalty;\nvar kEndPenalizedScore = 300;\nvar kCSSIdScore = 500;\nvar kRoleWithoutNameScore = 510;\nvar kCSSInputTypeNameScore = 520;\nvar kCSSTagNameScore = 530;\nvar kNthScore = 1e4;\nvar kCSSFallbackScore = 1e7;\nvar kScoreThresholdForTextExpect = 1e3;\nfunction generateSelector(injectedScript, targetElement, options) {\n var _a;\n injectedScript._evaluator.begin();\n const cache = { allowText: /* @__PURE__ */ new Map(), disallowText: /* @__PURE__ */ new Map() };\n beginAriaCaches();\n beginDOMCaches();\n try {\n let selectors = [];\n if (options.forTextExpect) {\n let targetTokens = cssFallback(injectedScript, targetElement.ownerDocument.documentElement, options);\n for (let element = targetElement; element; element = parentElementOrShadowHost(element)) {\n const tokens = generateSelectorFor(cache, injectedScript, element, { ...options, noText: true });\n if (!tokens)\n continue;\n const score = combineScores(tokens);\n if (score <= kScoreThresholdForTextExpect) {\n targetTokens = tokens;\n break;\n }\n }\n selectors = [joinTokens(targetTokens)];\n } else {\n if (!targetElement.matches("input,textarea,select") && !targetElement.isContentEditable) {\n const interactiveParent = closestCrossShadow(targetElement, "button,select,input,[role=button],[role=checkbox],[role=radio],a,[role=link]", options.root);\n if (interactiveParent && isElementVisible(interactiveParent))\n targetElement = interactiveParent;\n }\n if (options.multiple) {\n const withText = generateSelectorFor(cache, injectedScript, targetElement, options);\n const withoutText = generateSelectorFor(cache, injectedScript, targetElement, { ...options, noText: true });\n let tokens = [withText, withoutText];\n cache.allowText.clear();\n cache.disallowText.clear();\n if (withText && hasCSSIdToken(withText))\n tokens.push(generateSelectorFor(cache, injectedScript, targetElement, { ...options, noCSSId: true }));\n if (withoutText && hasCSSIdToken(withoutText))\n tokens.push(generateSelectorFor(cache, injectedScript, targetElement, { ...options, noText: true, noCSSId: true }));\n tokens = tokens.filter(Boolean);\n if (!tokens.length) {\n const css = cssFallback(injectedScript, targetElement, options);\n tokens.push(css);\n if (hasCSSIdToken(css))\n tokens.push(cssFallback(injectedScript, targetElement, { ...options, noCSSId: true }));\n }\n selectors = [...new Set(tokens.map((t) => joinTokens(t)))];\n } else {\n const targetTokens = generateSelectorFor(cache, injectedScript, targetElement, options) || cssFallback(injectedScript, targetElement, options);\n selectors = [joinTokens(targetTokens)];\n }\n }\n const selector = selectors[0];\n const parsedSelector = injectedScript.parseSelector(selector);\n return {\n selector,\n selectors,\n elements: injectedScript.querySelectorAll(parsedSelector, (_a = options.root) != null ? _a : targetElement.ownerDocument)\n };\n } finally {\n endDOMCaches();\n endAriaCaches();\n injectedScript._evaluator.end();\n }\n}\nfunction generateSelectorFor(cache, injectedScript, targetElement, options) {\n var _a;\n if (options.root && !isInsideScope(options.root, targetElement))\n throw new Error(`Target element must belong to the root\'s subtree`);\n if (targetElement === options.root)\n return [{ engine: "css", selector: ":scope", score: 1 }];\n if (targetElement.ownerDocument.documentElement === targetElement)\n return [{ engine: "css", selector: "html", score: 1 }];\n let result = null;\n const updateResult = (candidate) => {\n if (!result || combineScores(candidate) < combineScores(result))\n result = candidate;\n };\n const candidates = [];\n if (!options.noText) {\n for (const candidate of buildTextCandidates(injectedScript, targetElement, !options.isRecursive))\n candidates.push({ candidate, isTextCandidate: true });\n }\n for (const token of buildNoTextCandidates(injectedScript, targetElement, options)) {\n if (options.omitInternalEngines && token.engine.startsWith("internal:"))\n continue;\n candidates.push({ candidate: [token], isTextCandidate: false });\n }\n candidates.sort((a, b) => combineScores(a.candidate) - combineScores(b.candidate));\n for (const { candidate, isTextCandidate } of candidates) {\n const elements = injectedScript.querySelectorAll(injectedScript.parseSelector(joinTokens(candidate)), (_a = options.root) != null ? _a : targetElement.ownerDocument);\n if (!elements.includes(targetElement)) {\n continue;\n }\n if (elements.length === 1) {\n updateResult(candidate);\n break;\n }\n const index = elements.indexOf(targetElement);\n if (index > 5) {\n continue;\n }\n updateResult([...candidate, { engine: "nth", selector: String(index), score: kNthScore }]);\n if (options.isRecursive) {\n continue;\n }\n for (let parent = parentElementOrShadowHost(targetElement); parent && parent !== options.root; parent = parentElementOrShadowHost(parent)) {\n const filtered = elements.filter((e) => isInsideScope(parent, e) && e !== parent);\n const newIndex = filtered.indexOf(targetElement);\n if (filtered.length > 5 || newIndex === -1 || newIndex === index && filtered.length > 1) {\n continue;\n }\n const inParent = filtered.length === 1 ? candidate : [...candidate, { engine: "nth", selector: String(newIndex), score: kNthScore }];\n const idealSelectorForParent = { engine: "", selector: "", score: 1 };\n if (result && combineScores([idealSelectorForParent, ...inParent]) >= combineScores(result)) {\n continue;\n }\n const noText = !!options.noText || isTextCandidate;\n const cacheMap = noText ? cache.disallowText : cache.allowText;\n let parentTokens = cacheMap.get(parent);\n if (parentTokens === void 0) {\n parentTokens = generateSelectorFor(cache, injectedScript, parent, { ...options, isRecursive: true, noText }) || cssFallback(injectedScript, parent, options);\n cacheMap.set(parent, parentTokens);\n }\n if (!parentTokens)\n continue;\n updateResult([...parentTokens, ...inParent]);\n }\n }\n return result;\n}\nfunction buildNoTextCandidates(injectedScript, element, options) {\n const candidates = [];\n const testIdAttributeNames = splitTestIdAttributeNames(options.testIdAttributeName);\n {\n for (const attr of ["data-testid", "data-test-id", "data-test"]) {\n if (!testIdAttributeNames.includes(attr) && element.getAttribute(attr))\n candidates.push({ engine: "css", selector: `[${attr}=${quoteCSSAttributeValue(element.getAttribute(attr))}]`, score: kOtherTestIdScore });\n }\n if (!options.noCSSId) {\n const idAttr = element.getAttribute("id");\n if (idAttr && !isGuidLike(idAttr))\n candidates.push({ engine: "css", selector: makeSelectorForId(idAttr), score: kCSSIdScore });\n }\n candidates.push({ engine: "css", selector: escapeNodeName(element), score: kCSSTagNameScore });\n }\n if (element.nodeName === "IFRAME") {\n for (const attribute of ["name", "title"]) {\n if (element.getAttribute(attribute))\n candidates.push({ engine: "css", selector: `${escapeNodeName(element)}[${attribute}=${quoteCSSAttributeValue(element.getAttribute(attribute))}]`, score: kIframeByAttributeScore });\n }\n for (const testIdAttr of testIdAttributeNames) {\n if (element.getAttribute(testIdAttr))\n candidates.push({ engine: "css", selector: `[${testIdAttr}=${quoteCSSAttributeValue(element.getAttribute(testIdAttr))}]`, score: kTestIdScore });\n }\n penalizeScoreForLength([candidates]);\n return candidates;\n }\n for (const testIdAttr of testIdAttributeNames) {\n if (element.getAttribute(testIdAttr))\n candidates.push({ engine: "internal:testid", selector: `[${testIdAttr}=${escapeForAttributeSelector(element.getAttribute(testIdAttr), true)}]`, score: kTestIdScore });\n }\n if (element.nodeName === "INPUT" || element.nodeName === "TEXTAREA") {\n const input = element;\n if (input.placeholder) {\n candidates.push({ engine: "internal:attr", selector: `[placeholder=${escapeForAttributeSelector(input.placeholder, true)}]`, score: kPlaceholderScoreExact });\n for (const alternative of suitableTextAlternatives(input.placeholder))\n candidates.push({ engine: "internal:attr", selector: `[placeholder=${escapeForAttributeSelector(alternative.text, false)}]`, score: kPlaceholderScore - alternative.scoreBonus });\n }\n }\n const labels = getElementLabels(injectedScript._evaluator._cacheText, element);\n for (const label of labels) {\n const labelText = label.normalized;\n candidates.push({ engine: "internal:label", selector: escapeForTextSelector(labelText, true), score: kLabelScoreExact });\n for (const alternative of suitableTextAlternatives(labelText))\n candidates.push({ engine: "internal:label", selector: escapeForTextSelector(alternative.text, false), score: kLabelScore - alternative.scoreBonus });\n }\n const ariaRole = getAriaRole(element);\n if (ariaRole && !["none", "presentation"].includes(ariaRole))\n candidates.push({ engine: "internal:role", selector: ariaRole, score: kRoleWithoutNameScore });\n if (element.getAttribute("name") && ["BUTTON", "FORM", "FIELDSET", "FRAME", "IFRAME", "INPUT", "KEYGEN", "OBJECT", "OUTPUT", "SELECT", "TEXTAREA", "MAP", "META", "PARAM"].includes(element.nodeName))\n candidates.push({ engine: "css", selector: `${escapeNodeName(element)}[name=${quoteCSSAttributeValue(element.getAttribute("name"))}]`, score: kCSSInputTypeNameScore });\n if (["INPUT", "TEXTAREA"].includes(element.nodeName) && element.getAttribute("type") !== "hidden") {\n if (element.getAttribute("type"))\n candidates.push({ engine: "css", selector: `${escapeNodeName(element)}[type=${quoteCSSAttributeValue(element.getAttribute("type"))}]`, score: kCSSInputTypeNameScore });\n }\n if (["INPUT", "TEXTAREA", "SELECT"].includes(element.nodeName) && element.getAttribute("type") !== "hidden")\n candidates.push({ engine: "css", selector: escapeNodeName(element), score: kCSSInputTypeNameScore + 1 });\n penalizeScoreForLength([candidates]);\n return candidates;\n}\nfunction buildTextCandidates(injectedScript, element, isTargetNode) {\n if (element.nodeName === "SELECT")\n return [];\n const candidates = [];\n const title = element.getAttribute("title");\n if (title) {\n candidates.push([{ engine: "internal:attr", selector: `[title=${escapeForAttributeSelector(title, true)}]`, score: kTitleScoreExact }]);\n for (const alternative of suitableTextAlternatives(title))\n candidates.push([{ engine: "internal:attr", selector: `[title=${escapeForAttributeSelector(alternative.text, false)}]`, score: kTitleScore - alternative.scoreBonus }]);\n }\n const alt = element.getAttribute("alt");\n if (alt && ["APPLET", "AREA", "IMG", "INPUT"].includes(element.nodeName)) {\n candidates.push([{ engine: "internal:attr", selector: `[alt=${escapeForAttributeSelector(alt, true)}]`, score: kAltTextScoreExact }]);\n for (const alternative of suitableTextAlternatives(alt))\n candidates.push([{ engine: "internal:attr", selector: `[alt=${escapeForAttributeSelector(alternative.text, false)}]`, score: kAltTextScore - alternative.scoreBonus }]);\n }\n const text = elementText(injectedScript._evaluator._cacheText, element).normalized;\n const textAlternatives = text ? suitableTextAlternatives(text) : [];\n if (text) {\n if (isTargetNode) {\n if (text.length <= 80)\n candidates.push([{ engine: "internal:text", selector: escapeForTextSelector(text, true), score: kTextScoreExact }]);\n for (const alternative of textAlternatives)\n candidates.push([{ engine: "internal:text", selector: escapeForTextSelector(alternative.text, false), score: kTextScore - alternative.scoreBonus }]);\n }\n const cssToken = { engine: "css", selector: escapeNodeName(element), score: kCSSTagNameScore };\n for (const alternative of textAlternatives)\n candidates.push([cssToken, { engine: "internal:has-text", selector: escapeForTextSelector(alternative.text, false), score: kTextScore - alternative.scoreBonus }]);\n if (isTargetNode && text.length <= 80) {\n const re = new RegExp("^" + escapeRegExp(text) + "$");\n candidates.push([cssToken, { engine: "internal:has-text", selector: escapeForTextSelector(re, false), score: kTextScoreRegex }]);\n }\n }\n const ariaRole = getAriaRole(element);\n if (ariaRole && !["none", "presentation"].includes(ariaRole)) {\n const ariaName = getElementAccessibleName(element, false);\n if (ariaName && !ariaName.match(/^\\p{Co}+$/u)) {\n const roleToken = { engine: "internal:role", selector: `${ariaRole}[name=${escapeForAttributeSelector(ariaName, true)}]`, score: kRoleWithNameScoreExact };\n candidates.push([roleToken]);\n for (const alternative of suitableTextAlternatives(ariaName))\n candidates.push([{ engine: "internal:role", selector: `${ariaRole}[name=${escapeForAttributeSelector(alternative.text, false)}]`, score: kRoleWithNameScore - alternative.scoreBonus }]);\n const ariaDescription = getElementAccessibleDescription(element, false);\n if (ariaDescription) {\n candidates.push([{ engine: "internal:role", selector: `${ariaRole}[name=${escapeForAttributeSelector(ariaName, true)}][description=${escapeForAttributeSelector(ariaDescription, true)}]`, score: kRoleWithNameScoreExact + 1 }]);\n for (const alternative of suitableTextAlternatives(ariaName))\n candidates.push([{ engine: "internal:role", selector: `${ariaRole}[name=${escapeForAttributeSelector(alternative.text, false)}][description=${escapeForAttributeSelector(ariaDescription, false)}]`, score: kRoleWithNameScore - alternative.scoreBonus + 1 }]);\n }\n } else {\n const roleToken = { engine: "internal:role", selector: `${ariaRole}`, score: kRoleWithoutNameScore };\n const ariaDescription = getElementAccessibleDescription(element, false);\n if (ariaDescription)\n candidates.push([{ engine: "internal:role", selector: `${ariaRole}[description=${escapeForAttributeSelector(ariaDescription, true)}]`, score: kRoleWithoutNameScore + 1 }]);\n for (const alternative of textAlternatives)\n candidates.push([roleToken, { engine: "internal:has-text", selector: escapeForTextSelector(alternative.text, false), score: kTextScore - alternative.scoreBonus }]);\n if (isTargetNode && text.length <= 80) {\n const re = new RegExp("^" + escapeRegExp(text) + "$");\n candidates.push([roleToken, { engine: "internal:has-text", selector: escapeForTextSelector(re, false), score: kTextScoreRegex }]);\n }\n }\n }\n penalizeScoreForLength(candidates);\n return candidates;\n}\nfunction makeSelectorForId(id) {\n return /^[a-zA-Z][a-zA-Z0-9\\-\\_]+$/.test(id) ? "#" + id : `[id=${quoteCSSAttributeValue(id)}]`;\n}\nfunction hasCSSIdToken(tokens) {\n return tokens.some((token) => token.engine === "css" && (token.selector.startsWith("#") || token.selector.startsWith(\'[id="\')));\n}\nfunction cssFallback(injectedScript, targetElement, options) {\n var _a;\n const root = (_a = options.root) != null ? _a : targetElement.ownerDocument;\n const tokens = [];\n function uniqueCSSSelector(prefix) {\n const path = tokens.slice();\n if (prefix)\n path.unshift(prefix);\n const selector = path.join(" > ");\n const parsedSelector = injectedScript.parseSelector(selector);\n const node = injectedScript.querySelector(parsedSelector, root, false);\n return node === targetElement ? selector : void 0;\n }\n function makeStrict(selector) {\n const token = { engine: "css", selector, score: kCSSFallbackScore };\n const parsedSelector = injectedScript.parseSelector(selector);\n const elements = injectedScript.querySelectorAll(parsedSelector, root);\n if (elements.length === 1)\n return [token];\n const nth = { engine: "nth", selector: String(elements.indexOf(targetElement)), score: kNthScore };\n return [token, nth];\n }\n for (let element = targetElement; element && element !== root; element = parentElementOrShadowHost(element)) {\n let bestTokenForLevel = "";\n if (element.id && !options.noCSSId) {\n const token = makeSelectorForId(element.id);\n const selector = uniqueCSSSelector(token);\n if (selector)\n return makeStrict(selector);\n bestTokenForLevel = token;\n }\n const parent = element.parentNode;\n const classes = [...element.classList].map(escapeClassName);\n for (let i = 0; i < classes.length; ++i) {\n const token = "." + classes.slice(0, i + 1).join(".");\n const selector = uniqueCSSSelector(token);\n if (selector)\n return makeStrict(selector);\n if (!bestTokenForLevel && parent) {\n const sameClassSiblings = parent.querySelectorAll(token);\n if (sameClassSiblings.length === 1)\n bestTokenForLevel = token;\n }\n }\n if (parent) {\n const siblings = [...parent.children];\n const nodeName = element.nodeName;\n const sameTagSiblings = siblings.filter((sibling) => sibling.nodeName === nodeName);\n const token = sameTagSiblings.indexOf(element) === 0 ? escapeNodeName(element) : `${escapeNodeName(element)}:nth-child(${1 + siblings.indexOf(element)})`;\n const selector = uniqueCSSSelector(token);\n if (selector)\n return makeStrict(selector);\n if (!bestTokenForLevel)\n bestTokenForLevel = token;\n } else if (!bestTokenForLevel) {\n bestTokenForLevel = escapeNodeName(element);\n }\n tokens.unshift(bestTokenForLevel);\n }\n return makeStrict(uniqueCSSSelector());\n}\nfunction penalizeScoreForLength(groups) {\n for (const group of groups) {\n for (const token of group) {\n if (token.score > kBeginPenalizedScore && token.score < kEndPenalizedScore)\n token.score += Math.min(kTextScoreRange, token.selector.length / 10 | 0);\n }\n }\n}\nfunction joinTokens(tokens) {\n const parts = [];\n let lastEngine = "";\n for (const { engine, selector } of tokens) {\n if (parts.length && (lastEngine !== "css" || engine !== "css" || selector.startsWith(":nth-match(")))\n parts.push(">>");\n lastEngine = engine;\n if (engine === "css")\n parts.push(selector);\n else\n parts.push(`${engine}=${selector}`);\n }\n return parts.join(" ");\n}\nfunction combineScores(tokens) {\n let score = 0;\n for (let i = 0; i < tokens.length; i++)\n score += tokens[i].score * (tokens.length - i);\n return score;\n}\nfunction isGuidLike(id) {\n let lastCharacterType;\n let transitionCount = 0;\n for (let i = 0; i < id.length; ++i) {\n const c = id[i];\n let characterType;\n if (c === "-" || c === "_")\n continue;\n if (c >= "a" && c <= "z")\n characterType = "lower";\n else if (c >= "A" && c <= "Z")\n characterType = "upper";\n else if (c >= "0" && c <= "9")\n characterType = "digit";\n else\n characterType = "other";\n if (characterType === "lower" && lastCharacterType === "upper") {\n lastCharacterType = characterType;\n continue;\n }\n if (lastCharacterType && lastCharacterType !== characterType)\n ++transitionCount;\n lastCharacterType = characterType;\n }\n return transitionCount >= id.length / 4;\n}\nfunction trimWordBoundary(text, maxLength) {\n if (text.length <= maxLength)\n return text;\n text = text.substring(0, maxLength);\n const match = text.match(/^(.*)\\b(.+?)$/);\n if (!match)\n return "";\n return match[1].trimEnd();\n}\nfunction suitableTextAlternatives(text) {\n let result = [];\n {\n const match = text.match(/^([\\d.,]+)[^.,\\w]/);\n const leadingNumberLength = match ? match[1].length : 0;\n if (leadingNumberLength) {\n const alt = trimWordBoundary(text.substring(leadingNumberLength).trimStart(), 80);\n result.push({ text: alt, scoreBonus: alt.length <= 30 ? 2 : 1 });\n }\n }\n {\n const match = text.match(/[^.,\\w]([\\d.,]+)$/);\n const trailingNumberLength = match ? match[1].length : 0;\n if (trailingNumberLength) {\n const alt = trimWordBoundary(text.substring(0, text.length - trailingNumberLength).trimEnd(), 80);\n result.push({ text: alt, scoreBonus: alt.length <= 30 ? 2 : 1 });\n }\n }\n if (text.length <= 30) {\n result.push({ text, scoreBonus: 0 });\n } else {\n result.push({ text: trimWordBoundary(text, 80), scoreBonus: 0 });\n result.push({ text: trimWordBoundary(text, 30), scoreBonus: 1 });\n }\n result = result.filter((r) => r.text);\n if (!result.length)\n result.push({ text: text.substring(0, 80), scoreBonus: 0 });\n return result;\n}\nfunction escapeNodeName(node) {\n return node.nodeName.toLocaleLowerCase().replace(/[:\\.]/g, (char) => "\\\\" + char);\n}\nfunction escapeClassName(className) {\n let result = "";\n for (let i = 0; i < className.length; i++)\n result += cssEscapeCharacter(className, i);\n return result;\n}\nfunction cssEscapeCharacter(s, i) {\n const c = s.charCodeAt(i);\n if (c === 0)\n return "\\uFFFD";\n if (c >= 1 && c <= 31 || c >= 48 && c <= 57 && (i === 0 || i === 1 && s.charCodeAt(0) === 45))\n return "\\\\" + c.toString(16) + " ";\n if (i === 0 && c === 45 && s.length === 1)\n return "\\\\" + s.charAt(i);\n if (c >= 128 || c === 45 || c === 95 || c >= 48 && c <= 57 || c >= 65 && c <= 90 || c >= 97 && c <= 122)\n return s.charAt(i);\n return "\\\\" + s.charAt(i);\n}\n\n// packages/injected/src/xpathSelectorEngine.ts\nvar XPathEngine = {\n queryAll(root, selector) {\n if (selector.startsWith("/") && root.nodeType !== Node.DOCUMENT_NODE)\n selector = "." + selector;\n const result = [];\n const document = root.ownerDocument || root;\n if (!document)\n return result;\n const it = document.evaluate(selector, root, null, XPathResult.ORDERED_NODE_ITERATOR_TYPE);\n for (let node = it.iterateNext(); node; node = it.iterateNext()) {\n if (node.nodeType === Node.ELEMENT_NODE)\n result.push(node);\n }\n return result;\n }\n};\n\n// packages/injected/src/consoleApi.ts\nvar selectorSymbol = Symbol("selector");\nselectorSymbol;\nvar _Locator = class _Locator {\n constructor(injectedScript, selector, options) {\n if (options == null ? void 0 : options.hasText)\n selector += ` >> internal:has-text=${escapeForTextSelector(options.hasText, false)}`;\n if (options == null ? void 0 : options.hasNotText)\n selector += ` >> internal:has-not-text=${escapeForTextSelector(options.hasNotText, false)}`;\n if (options == null ? void 0 : options.has)\n selector += ` >> internal:has=` + JSON.stringify(options.has[selectorSymbol]);\n if (options == null ? void 0 : options.hasNot)\n selector += ` >> internal:has-not=` + JSON.stringify(options.hasNot[selectorSymbol]);\n if ((options == null ? void 0 : options.visible) !== void 0)\n selector += ` >> visible=${options.visible ? "true" : "false"}`;\n this[selectorSymbol] = selector;\n if (selector) {\n const parsed = injectedScript.parseSelector(selector);\n this.element = injectedScript.querySelector(parsed, injectedScript.document, false);\n this.elements = injectedScript.querySelectorAll(parsed, injectedScript.document);\n }\n const selectorBase = selector;\n const self = this;\n self.locator = (selector2, options2) => {\n return new _Locator(injectedScript, selectorBase ? selectorBase + " >> " + selector2 : selector2, options2);\n };\n self.getByTestId = (testId) => self.locator(getByTestIdSelector(injectedScript.testIdAttributeNameForStrictErrorAndConsoleCodegen(), testId));\n self.getByAltText = (text, options2) => self.locator(getByAltTextSelector(text, options2));\n self.getByLabel = (text, options2) => self.locator(getByLabelSelector(text, options2));\n self.getByPlaceholder = (text, options2) => self.locator(getByPlaceholderSelector(text, options2));\n self.getByText = (text, options2) => self.locator(getByTextSelector(text, options2));\n self.getByTitle = (text, options2) => self.locator(getByTitleSelector(text, options2));\n self.getByRole = (role, options2 = {}) => self.locator(getByRoleSelector(role, options2));\n self.filter = (options2) => new _Locator(injectedScript, selector, options2);\n self.first = () => self.locator("nth=0");\n self.last = () => self.locator("nth=-1");\n self.nth = (index) => self.locator(`nth=${index}`);\n self.and = (locator) => new _Locator(injectedScript, selectorBase + ` >> internal:and=` + JSON.stringify(locator[selectorSymbol]));\n self.or = (locator) => new _Locator(injectedScript, selectorBase + ` >> internal:or=` + JSON.stringify(locator[selectorSymbol]));\n }\n};\nvar Locator = _Locator;\nvar ConsoleAPI = class {\n constructor(injectedScript) {\n this._injectedScript = injectedScript;\n }\n install() {\n if (this._injectedScript.window.playwright)\n return;\n this._injectedScript.window.playwright = {\n $: (selector, strict) => this._querySelector(selector, !!strict),\n $$: (selector) => this._querySelectorAll(selector),\n inspect: (selector) => this._inspect(selector),\n selector: (element) => this._selector(element),\n generateLocator: (element, language) => this._generateLocator(element, language),\n ariaSnapshot: (element, options) => {\n return this._injectedScript.ariaSnapshot(element || this._injectedScript.document.body, options || { mode: "default" });\n },\n resume: () => this._resume(),\n ...new Locator(this._injectedScript, "")\n };\n delete this._injectedScript.window.playwright.filter;\n delete this._injectedScript.window.playwright.first;\n delete this._injectedScript.window.playwright.last;\n delete this._injectedScript.window.playwright.nth;\n delete this._injectedScript.window.playwright.and;\n delete this._injectedScript.window.playwright.or;\n }\n _querySelector(selector, strict) {\n if (typeof selector !== "string")\n throw new Error(`Usage: playwright.query(\'Playwright >> selector\').`);\n const parsed = this._injectedScript.parseSelector(selector);\n return this._injectedScript.querySelector(parsed, this._injectedScript.document, strict);\n }\n _querySelectorAll(selector) {\n if (typeof selector !== "string")\n throw new Error(`Usage: playwright.$$(\'Playwright >> selector\').`);\n const parsed = this._injectedScript.parseSelector(selector);\n return this._injectedScript.querySelectorAll(parsed, this._injectedScript.document);\n }\n _inspect(selector) {\n if (typeof selector !== "string")\n throw new Error(`Usage: playwright.inspect(\'Playwright >> selector\').`);\n this._injectedScript.window.inspect(this._querySelector(selector, false));\n }\n _selector(element) {\n if (!(element instanceof Element))\n throw new Error(`Usage: playwright.selector(element).`);\n return this._injectedScript.generateSelectorSimple(element);\n }\n _generateLocator(element, language) {\n if (!(element instanceof Element))\n throw new Error(`Usage: playwright.locator(element).`);\n const selector = this._injectedScript.generateSelectorSimple(element);\n return asLocator(language || "javascript", selector);\n }\n _resume() {\n if (!this._injectedScript.window.__pw_resume)\n return false;\n this._injectedScript.window.__pw_resume().catch(() => {\n });\n }\n};\n\n// packages/isomorphic/utilityScriptSerializers.ts\nfunction isRegExp2(obj) {\n try {\n return obj instanceof RegExp || Object.prototype.toString.call(obj) === "[object RegExp]";\n } catch (error) {\n return false;\n }\n}\nfunction isDate(obj) {\n try {\n return obj instanceof Date || Object.prototype.toString.call(obj) === "[object Date]";\n } catch (error) {\n return false;\n }\n}\nfunction isURL(obj) {\n try {\n return obj instanceof URL || Object.prototype.toString.call(obj) === "[object URL]";\n } catch (error) {\n return false;\n }\n}\nfunction isError(obj) {\n var _a;\n try {\n return obj instanceof Error || obj && ((_a = Object.getPrototypeOf(obj)) == null ? void 0 : _a.name) === "Error";\n } catch (error) {\n return false;\n }\n}\nfunction isTypedArray(obj, constructor) {\n try {\n return obj instanceof constructor || Object.prototype.toString.call(obj) === `[object ${constructor.name}]`;\n } catch (error) {\n return false;\n }\n}\nfunction isArrayBuffer(obj) {\n try {\n return obj instanceof ArrayBuffer || Object.prototype.toString.call(obj) === "[object ArrayBuffer]";\n } catch (error) {\n return false;\n }\n}\nvar typedArrayConstructors = {\n i8: Int8Array,\n ui8: Uint8Array,\n ui8c: Uint8ClampedArray,\n i16: Int16Array,\n ui16: Uint16Array,\n i32: Int32Array,\n ui32: Uint32Array,\n // TODO: add Float16Array once it\'s in baseline\n f32: Float32Array,\n f64: Float64Array,\n bi64: BigInt64Array,\n bui64: BigUint64Array\n};\nfunction typedArrayToBase64(array) {\n if ("toBase64" in array)\n return array.toBase64();\n const binary = Array.from(new Uint8Array(array.buffer, array.byteOffset, array.byteLength)).map((b) => String.fromCharCode(b)).join("");\n return btoa(binary);\n}\nfunction base64ToTypedArray(base64, TypedArrayConstructor) {\n const binary = atob(base64);\n const bytes = new Uint8Array(binary.length);\n for (let i = 0; i < binary.length; i++)\n bytes[i] = binary.charCodeAt(i);\n return new TypedArrayConstructor(bytes.buffer);\n}\nfunction parseEvaluationResultValue(value, handles = [], refs = /* @__PURE__ */ new Map()) {\n if (Object.is(value, void 0))\n return void 0;\n if (typeof value === "object" && value) {\n if ("ref" in value)\n return refs.get(value.ref);\n if ("v" in value) {\n if (value.v === "undefined")\n return void 0;\n if (value.v === "null")\n return null;\n if (value.v === "NaN")\n return NaN;\n if (value.v === "Infinity")\n return Infinity;\n if (value.v === "-Infinity")\n return -Infinity;\n if (value.v === "-0")\n return -0;\n return void 0;\n }\n if ("d" in value) {\n return new Date(value.d);\n }\n if ("u" in value)\n return new URL(value.u);\n if ("bi" in value)\n return BigInt(value.bi);\n if ("e" in value) {\n const error = new Error(value.e.m);\n error.name = value.e.n;\n error.stack = value.e.s;\n return error;\n }\n if ("r" in value)\n return new RegExp(value.r.p, value.r.f);\n if ("a" in value) {\n const result = [];\n refs.set(value.id, result);\n for (const a of value.a)\n result.push(parseEvaluationResultValue(a, handles, refs));\n return result;\n }\n if ("o" in value) {\n const result = {};\n refs.set(value.id, result);\n for (const { k, v } of value.o) {\n if (k === "__proto__")\n continue;\n result[k] = parseEvaluationResultValue(v, handles, refs);\n }\n return result;\n }\n if ("h" in value)\n return handles[value.h];\n if ("ta" in value)\n return base64ToTypedArray(value.ta.b, typedArrayConstructors[value.ta.k]);\n if ("ab" in value)\n return base64ToTypedArray(value.ab.b, Uint8Array).buffer;\n }\n return value;\n}\nfunction serializeAsCallArgument(value, handleSerializer) {\n return serialize(value, handleSerializer, { visited: /* @__PURE__ */ new Map(), lastId: 0 });\n}\nfunction serialize(value, handleSerializer, visitorInfo) {\n if (value && typeof value === "object") {\n if (typeof globalThis.Window === "function" && value instanceof globalThis.Window)\n return "ref: ";\n if (typeof globalThis.Document === "function" && value instanceof globalThis.Document)\n return "ref: ";\n if (typeof globalThis.Node === "function" && value instanceof globalThis.Node)\n return "ref: ";\n }\n return innerSerialize(value, handleSerializer, visitorInfo);\n}\nfunction innerSerialize(value, handleSerializer, visitorInfo) {\n var _a;\n const result = handleSerializer(value);\n if ("fallThrough" in result)\n value = result.fallThrough;\n else\n return result;\n if (typeof value === "symbol")\n return { v: "undefined" };\n if (Object.is(value, void 0))\n return { v: "undefined" };\n if (Object.is(value, null))\n return { v: "null" };\n if (Object.is(value, NaN))\n return { v: "NaN" };\n if (Object.is(value, Infinity))\n return { v: "Infinity" };\n if (Object.is(value, -Infinity))\n return { v: "-Infinity" };\n if (Object.is(value, -0))\n return { v: "-0" };\n if (typeof value === "boolean")\n return value;\n if (typeof value === "number")\n return value;\n if (typeof value === "string")\n return value;\n if (typeof value === "bigint")\n return { bi: value.toString() };\n if (isError(value)) {\n let stack;\n if ((_a = value.stack) == null ? void 0 : _a.startsWith(value.name + ": " + value.message)) {\n stack = value.stack;\n } else {\n stack = `${value.name}: ${value.message}\n${value.stack}`;\n }\n return { e: { n: value.name, m: value.message, s: stack } };\n }\n if (isDate(value))\n return { d: value.toJSON() };\n if (isURL(value))\n return { u: value.toJSON() };\n if (isRegExp2(value))\n return { r: { p: value.source, f: value.flags } };\n for (const [k, ctor] of Object.entries(typedArrayConstructors)) {\n if (isTypedArray(value, ctor))\n return { ta: { b: typedArrayToBase64(value), k } };\n }\n if (isArrayBuffer(value))\n return { ab: { b: typedArrayToBase64(new Uint8Array(value)) } };\n const id = visitorInfo.visited.get(value);\n if (id)\n return { ref: id };\n if (Array.isArray(value)) {\n const a = [];\n const id2 = ++visitorInfo.lastId;\n visitorInfo.visited.set(value, id2);\n for (let i = 0; i < value.length; ++i)\n a.push(serialize(value[i], handleSerializer, visitorInfo));\n return { a, id: id2 };\n }\n if (typeof value === "object") {\n const o = [];\n const id2 = ++visitorInfo.lastId;\n visitorInfo.visited.set(value, id2);\n for (const name of Object.keys(value)) {\n let item;\n try {\n item = value[name];\n } catch (e) {\n continue;\n }\n if (name === "toJSON" && typeof item === "function")\n o.push({ k: name, v: { o: [], id: 0 } });\n else\n o.push({ k: name, v: serialize(item, handleSerializer, visitorInfo) });\n }\n let jsonWrapper;\n try {\n if (o.length === 0 && value.toJSON && typeof value.toJSON === "function")\n jsonWrapper = { value: value.toJSON() };\n } catch (e) {\n }\n if (jsonWrapper)\n return innerSerialize(jsonWrapper.value, handleSerializer, visitorInfo);\n return { o, id: id2 };\n }\n}\n\n// packages/injected/src/utilityScript.ts\nvar UtilityScript = class {\n constructor(global, isUnderTest) {\n var _a, _b, _c, _d, _e, _f, _g, _h;\n this.global = global;\n this.isUnderTest = isUnderTest;\n if (global.__pwClock) {\n this.builtins = global.__pwClock.builtins;\n } else {\n this.builtins = {\n setTimeout: (_a = global.setTimeout) == null ? void 0 : _a.bind(global),\n clearTimeout: (_b = global.clearTimeout) == null ? void 0 : _b.bind(global),\n setInterval: (_c = global.setInterval) == null ? void 0 : _c.bind(global),\n clearInterval: (_d = global.clearInterval) == null ? void 0 : _d.bind(global),\n requestAnimationFrame: (_e = global.requestAnimationFrame) == null ? void 0 : _e.bind(global),\n cancelAnimationFrame: (_f = global.cancelAnimationFrame) == null ? void 0 : _f.bind(global),\n requestIdleCallback: (_g = global.requestIdleCallback) == null ? void 0 : _g.bind(global),\n cancelIdleCallback: (_h = global.cancelIdleCallback) == null ? void 0 : _h.bind(global),\n performance: global.performance,\n Intl: global.Intl,\n Date: global.Date,\n AbortSignal: global.AbortSignal\n };\n }\n if (this.isUnderTest)\n global.builtins = this.builtins;\n }\n evaluate(isFunction, returnByValue, expression, argCount, ...argsAndHandles) {\n const args = argsAndHandles.slice(0, argCount);\n const handles = argsAndHandles.slice(argCount);\n const parameters = [];\n for (let i = 0; i < args.length; i++)\n parameters[i] = parseEvaluationResultValue(args[i], handles);\n let result = this.global.eval(expression);\n if (isFunction === true) {\n result = result(...parameters);\n } else if (isFunction === false) {\n result = result;\n } else {\n if (typeof result === "function")\n result = result(...parameters);\n }\n return returnByValue ? this._promiseAwareJsonValueNoThrow(result) : result;\n }\n jsonValue(returnByValue, value) {\n if (value === void 0)\n return void 0;\n return serializeAsCallArgument(value, (value2) => ({ fallThrough: value2 }));\n }\n _promiseAwareJsonValueNoThrow(value) {\n const safeJson = (value2) => {\n try {\n return this.jsonValue(true, value2);\n } catch (e) {\n return void 0;\n }\n };\n if (value && typeof value === "object" && typeof value.then === "function") {\n return (async () => {\n const promiseValue = await value;\n return safeJson(promiseValue);\n })();\n }\n return safeJson(value);\n }\n};\n\n// packages/injected/src/injectedScript.ts\nvar InjectedScript = class {\n constructor(window, options) {\n this._testIdAttributeNameForStrictErrorAndConsoleCodegen = "data-testid";\n this._lastAriaSnapshotForTrack = /* @__PURE__ */ new Map();\n // Recorder must use any external dependencies through InjectedScript.\n // Otherwise it will end up with a copy of all modules it uses, and any\n // module-level globals will be duplicated, which leads to subtle bugs.\n this.utils = {\n asLocator,\n cacheNormalizedWhitespaces,\n elementText,\n getAriaRole,\n getElementAccessibleDescription,\n getElementAccessibleName,\n isElementVisible,\n isInsideScope,\n normalizeWhiteSpace,\n parseAriaSnapshot,\n generateAriaTree,\n findNewElement,\n // Builtins protect injected code from clock emulation.\n builtins: null\n };\n this.window = window;\n this.document = window.document;\n this.isUnderTest = options.isUnderTest;\n this.utils.builtins = new UtilityScript(window, options.isUnderTest).builtins;\n this._sdkLanguage = options.sdkLanguage;\n this._testIdAttributeNameForStrictErrorAndConsoleCodegen = options.testIdAttributeName;\n this._evaluator = new SelectorEvaluatorImpl();\n this.consoleApi = new ConsoleAPI(this);\n this.onGlobalListenersRemoved = /* @__PURE__ */ new Set();\n this._autoClosingTags = /* @__PURE__ */ new Set(["AREA", "BASE", "BR", "COL", "COMMAND", "EMBED", "HR", "IMG", "INPUT", "KEYGEN", "LINK", "MENUITEM", "META", "PARAM", "SOURCE", "TRACK", "WBR"]);\n this._booleanAttributes = /* @__PURE__ */ new Set(["checked", "selected", "disabled", "readonly", "multiple"]);\n this._eventTypes = /* @__PURE__ */ new Map([\n ["auxclick", "mouse"],\n ["click", "mouse"],\n ["dblclick", "mouse"],\n ["mousedown", "mouse"],\n ["mouseeenter", "mouse"],\n ["mouseleave", "mouse"],\n ["mousemove", "mouse"],\n ["mouseout", "mouse"],\n ["mouseover", "mouse"],\n ["mouseup", "mouse"],\n ["mouseleave", "mouse"],\n ["mousewheel", "mouse"],\n ["keydown", "keyboard"],\n ["keyup", "keyboard"],\n ["keypress", "keyboard"],\n ["textInput", "keyboard"],\n ["touchstart", "touch"],\n ["touchmove", "touch"],\n ["touchend", "touch"],\n ["touchcancel", "touch"],\n ["pointerover", "pointer"],\n ["pointerout", "pointer"],\n ["pointerenter", "pointer"],\n ["pointerleave", "pointer"],\n ["pointerdown", "pointer"],\n ["pointerup", "pointer"],\n ["pointermove", "pointer"],\n ["pointercancel", "pointer"],\n ["gotpointercapture", "pointer"],\n ["lostpointercapture", "pointer"],\n ["focus", "focus"],\n ["blur", "focus"],\n ["drag", "drag"],\n ["dragstart", "drag"],\n ["dragend", "drag"],\n ["dragover", "drag"],\n ["dragenter", "drag"],\n ["dragleave", "drag"],\n ["dragexit", "drag"],\n ["drop", "drag"],\n ["wheel", "wheel"],\n ["deviceorientation", "deviceorientation"],\n ["deviceorientationabsolute", "deviceorientation"],\n ["devicemotion", "devicemotion"]\n ]);\n this._hoverHitTargetInterceptorEvents = /* @__PURE__ */ new Set(["mousemove"]);\n this._tapHitTargetInterceptorEvents = /* @__PURE__ */ new Set(["pointerdown", "pointerup", "touchstart", "touchend", "touchcancel"]);\n this._mouseHitTargetInterceptorEvents = /* @__PURE__ */ new Set(["mousedown", "mouseup", "pointerdown", "pointerup", "click", "auxclick", "dblclick", "contextmenu"]);\n this._allHitTargetInterceptorEvents = /* @__PURE__ */ new Set([...this._hoverHitTargetInterceptorEvents, ...this._tapHitTargetInterceptorEvents, ...this._mouseHitTargetInterceptorEvents]);\n this._engines = /* @__PURE__ */ new Map();\n this._engines.set("xpath", XPathEngine);\n this._engines.set("xpath:light", XPathEngine);\n this._engines.set("role", createRoleEngine(false));\n this._engines.set("text", this._createTextEngine(true, false));\n this._engines.set("text:light", this._createTextEngine(false, false));\n this._engines.set("id", this._createAttributeEngine("id", true));\n this._engines.set("id:light", this._createAttributeEngine("id", false));\n this._engines.set("data-testid", this._createAttributeEngine("data-testid", true));\n this._engines.set("data-testid:light", this._createAttributeEngine("data-testid", false));\n this._engines.set("data-test-id", this._createAttributeEngine("data-test-id", true));\n this._engines.set("data-test-id:light", this._createAttributeEngine("data-test-id", false));\n this._engines.set("data-test", this._createAttributeEngine("data-test", true));\n this._engines.set("data-test:light", this._createAttributeEngine("data-test", false));\n this._engines.set("css", this._createCSSEngine());\n this._engines.set("nth", { queryAll: () => [] });\n this._engines.set("visible", this._createVisibleEngine());\n this._engines.set("internal:control", this._createControlEngine());\n this._engines.set("internal:has", this._createHasEngine());\n this._engines.set("internal:has-not", this._createHasNotEngine());\n this._engines.set("internal:and", { queryAll: () => [] });\n this._engines.set("internal:or", { queryAll: () => [] });\n this._engines.set("internal:chain", this._createInternalChainEngine());\n this._engines.set("internal:label", this._createInternalLabelEngine());\n this._engines.set("internal:text", this._createTextEngine(true, true));\n this._engines.set("internal:has-text", this._createInternalHasTextEngine());\n this._engines.set("internal:has-not-text", this._createInternalHasNotTextEngine());\n this._engines.set("internal:attr", this._createNamedAttributeEngine());\n this._engines.set("internal:testid", this._createTestIdEngine());\n this._engines.set("internal:role", createRoleEngine(true));\n this._engines.set("internal:describe", this._createDescribeEngine());\n this._engines.set("aria-ref", this._createAriaRefEngine());\n for (const { name, source } of options.customEngines)\n this._engines.set(name, this.eval(source));\n this._stableRafCount = options.stableRafCount;\n this._browserName = options.browserName;\n this._shouldPrependErrorPrefix = !!options.shouldPrependErrorPrefix;\n this._isUtilityWorld = !!options.isUtilityWorld;\n setGlobalOptions({ browserNameForWorkarounds: options.browserName });\n this._setupGlobalListenersRemovalDetection();\n this._setupHitTargetInterceptors();\n if (this.isUnderTest)\n this.window.__injectedScript = this;\n }\n eval(expression) {\n return this.window.eval(expression);\n }\n testIdAttributeNameForStrictErrorAndConsoleCodegen() {\n return this._testIdAttributeNameForStrictErrorAndConsoleCodegen;\n }\n parseSelector(selector) {\n const result = parseSelector(selector);\n visitAllSelectorParts(result, (part) => {\n if (!this._engines.has(part.name))\n throw this.createStacklessError(`Unknown engine "${part.name}" while parsing selector ${selector}`);\n });\n return result;\n }\n generateSelector(targetElement, options) {\n return generateSelector(this, targetElement, options);\n }\n generateSelectorSimple(targetElement, options) {\n return generateSelector(this, targetElement, { ...options, testIdAttributeName: this._testIdAttributeNameForStrictErrorAndConsoleCodegen }).selector;\n }\n querySelector(selector, root, strict) {\n const result = this.querySelectorAll(selector, root);\n if (strict && result.length > 1)\n throw this.strictModeViolationError(selector, result);\n this.checkDeprecatedSelectorUsage(selector, result);\n return result[0];\n }\n _queryNth(elements, part) {\n const list = [...elements];\n let nth = +part.body;\n if (nth === -1)\n nth = list.length - 1;\n return new Set(list.slice(nth, nth + 1));\n }\n _queryLayoutSelector(elements, part, originalRoot) {\n const name = part.name;\n const body = part.body;\n const result = [];\n const inner = this.querySelectorAll(body.parsed, originalRoot);\n for (const element of elements) {\n const score = layoutSelectorScore(name, element, inner, body.distance);\n if (score !== void 0)\n result.push({ element, score });\n }\n result.sort((a, b) => a.score - b.score);\n return new Set(result.map((r) => r.element));\n }\n ariaSnapshot(node, options) {\n return this.incrementalAriaSnapshot(node, options).full;\n }\n incrementalAriaSnapshot(node, options) {\n if (node.nodeType !== Node.ELEMENT_NODE)\n throw this.createStacklessError("Can only capture aria snapshot of Element nodes.");\n const ariaSnapshot = generateAriaTree(node, options);\n const rendered = renderAriaTree(ariaSnapshot, options);\n let incremental;\n if (options.track) {\n const previousSnapshot = this._lastAriaSnapshotForTrack.get(options.track);\n if (previousSnapshot)\n incremental = renderAriaTree(ariaSnapshot, options, previousSnapshot).text;\n this._lastAriaSnapshotForTrack.set(options.track, ariaSnapshot);\n }\n this._lastAriaSnapshotForQuery = ariaSnapshot;\n return { full: rendered.text, incremental, iframeRefs: ariaSnapshot.iframeRefs, iframeDepths: rendered.iframeDepths };\n }\n ariaSnapshotForRecorder() {\n const tree = generateAriaTree(this.document.body, { mode: "ai" });\n const { text: ariaSnapshot } = renderAriaTree(tree, { mode: "ai" });\n return { ariaSnapshot, refs: tree.refs };\n }\n getAllElementsMatchingExpectAriaTemplate(document, template) {\n return getAllElementsMatchingExpectAriaTemplate(document.documentElement, template);\n }\n querySelectorAll(selector, root) {\n if (selector.capture !== void 0) {\n if (selector.parts.some((part) => part.name === "nth"))\n throw this.createStacklessError(`Can\'t query n-th element in a request with the capture.`);\n const withHas = { parts: selector.parts.slice(0, selector.capture + 1) };\n if (selector.capture < selector.parts.length - 1) {\n const parsed = { parts: selector.parts.slice(selector.capture + 1) };\n const has = { name: "internal:has", body: { parsed }, source: stringifySelector(parsed) };\n withHas.parts.push(has);\n }\n return this.querySelectorAll(withHas, root);\n }\n if (!root["querySelectorAll"])\n throw this.createStacklessError("Node is not queryable.");\n if (selector.capture !== void 0) {\n throw this.createStacklessError("Internal error: there should not be a capture in the selector.");\n }\n if (root.nodeType === 11 && selector.parts.length === 1 && selector.parts[0].name === "css" && selector.parts[0].source === ":scope")\n return [root];\n this._evaluator.begin();\n try {\n let roots = /* @__PURE__ */ new Set([root]);\n for (const part of selector.parts) {\n if (part.name === "nth") {\n roots = this._queryNth(roots, part);\n } else if (part.name === "internal:and") {\n const andElements = this.querySelectorAll(part.body.parsed, root);\n roots = new Set(andElements.filter((e) => roots.has(e)));\n } else if (part.name === "internal:or") {\n const orElements = this.querySelectorAll(part.body.parsed, root);\n roots = new Set(sortInDOMOrder(/* @__PURE__ */ new Set([...roots, ...orElements])));\n } else if (kLayoutSelectorNames.includes(part.name)) {\n roots = this._queryLayoutSelector(roots, part, root);\n } else {\n const next = /* @__PURE__ */ new Set();\n for (const root2 of roots) {\n const all = this._queryEngineAll(part, root2);\n for (const one of all)\n next.add(one);\n }\n roots = next;\n }\n }\n return [...roots];\n } finally {\n this._evaluator.end();\n }\n }\n _queryEngineAll(part, root) {\n const result = this._engines.get(part.name).queryAll(root, part.body);\n for (const element of result) {\n if (!("nodeName" in element))\n throw this.createStacklessError(`Expected a Node but got ${Object.prototype.toString.call(element)}`);\n }\n return result;\n }\n _createAttributeEngine(attribute, shadow) {\n const toCSS = (selector) => {\n const css = `[${attribute}=${JSON.stringify(selector)}]`;\n return [{ simples: [{ selector: { css, functions: [] }, combinator: "" }] }];\n };\n return {\n queryAll: (root, selector) => {\n return this._evaluator.query({ scope: root, pierceShadow: shadow }, toCSS(selector));\n }\n };\n }\n _createCSSEngine() {\n return {\n queryAll: (root, body) => {\n return this._evaluator.query({ scope: root, pierceShadow: true }, body);\n }\n };\n }\n _createTextEngine(shadow, internal) {\n const queryAll = (root, selector) => {\n const { matcher, kind } = createTextMatcher(selector, internal);\n const result = [];\n let lastDidNotMatchSelf = null;\n const appendElement = (element) => {\n if (kind === "lax" && lastDidNotMatchSelf && lastDidNotMatchSelf.contains(element))\n return false;\n const matches = elementMatchesText(this._evaluator._cacheText, element, matcher);\n if (matches === "none")\n lastDidNotMatchSelf = element;\n if (matches === "self" || matches === "selfAndChildren" && kind === "strict" && !internal)\n result.push(element);\n };\n if (root.nodeType === Node.ELEMENT_NODE)\n appendElement(root);\n const elements = this._evaluator._queryCSS({ scope: root, pierceShadow: shadow }, "*");\n for (const element of elements)\n appendElement(element);\n return result;\n };\n return { queryAll };\n }\n _createInternalHasTextEngine() {\n return {\n queryAll: (root, selector) => {\n if (root.nodeType !== 1)\n return [];\n const element = root;\n const text = elementText(this._evaluator._cacheText, element);\n const { matcher } = createTextMatcher(selector, true);\n return matcher(text) ? [element] : [];\n }\n };\n }\n _createInternalHasNotTextEngine() {\n return {\n queryAll: (root, selector) => {\n if (root.nodeType !== 1)\n return [];\n const element = root;\n const text = elementText(this._evaluator._cacheText, element);\n const { matcher } = createTextMatcher(selector, true);\n return matcher(text) ? [] : [element];\n }\n };\n }\n _createInternalLabelEngine() {\n return {\n queryAll: (root, selector) => {\n const { matcher } = createTextMatcher(selector, true);\n const allElements = this._evaluator._queryCSS({ scope: root, pierceShadow: true }, "*");\n return allElements.filter((element) => {\n return getElementLabels(this._evaluator._cacheText, element).some((label) => matcher(label));\n });\n }\n };\n }\n _createNamedAttributeEngine() {\n const queryAll = (root, selector) => {\n const parsed = parseAttributeSelector(selector, true);\n if (parsed.name || parsed.attributes.length !== 1)\n throw new Error("Malformed attribute selector: " + selector);\n const { name } = parsed.attributes[0];\n const matcher = createAttributeMatcher(parsed.attributes[0]);\n const elements = this._evaluator._queryCSS({ scope: root, pierceShadow: true }, `[${name}]`);\n return elements.filter((e) => matcher(e.getAttribute(name)));\n };\n return { queryAll };\n }\n _createTestIdEngine() {\n const queryAll = (root, selector) => {\n const parsed = parseAttributeSelector(selector, true);\n if (parsed.name || parsed.attributes.length !== 1)\n throw new Error("Malformed test id selector: " + selector);\n const names = splitTestIdAttributeNames(parsed.attributes[0].name);\n const matcher = createAttributeMatcher(parsed.attributes[0]);\n const cssQuery = names.map((n) => `[${n}]`).join(",");\n const elements = this._evaluator._queryCSS({ scope: root, pierceShadow: true }, cssQuery);\n return elements.filter((e) => names.some((n) => {\n const actual = e.getAttribute(n);\n return actual !== null && matcher(actual);\n }));\n };\n return { queryAll };\n }\n _createDescribeEngine() {\n const queryAll = (root) => {\n if (root.nodeType !== 1)\n return [];\n return [root];\n };\n return { queryAll };\n }\n _createControlEngine() {\n return {\n queryAll(root, body) {\n if (body === "enter-frame")\n return [];\n if (body === "return-empty")\n return [];\n if (body === "component") {\n if (root.nodeType !== 1)\n return [];\n return [root.childElementCount === 1 ? root.firstElementChild : root];\n }\n throw new Error(`Internal error, unknown internal:control selector ${body}`);\n }\n };\n }\n _createHasEngine() {\n const queryAll = (root, body) => {\n if (root.nodeType !== 1)\n return [];\n const has = !!this.querySelector(body.parsed, root, false);\n return has ? [root] : [];\n };\n return { queryAll };\n }\n _createHasNotEngine() {\n const queryAll = (root, body) => {\n if (root.nodeType !== 1)\n return [];\n const has = !!this.querySelector(body.parsed, root, false);\n return has ? [] : [root];\n };\n return { queryAll };\n }\n _createVisibleEngine() {\n const queryAll = (root, body) => {\n if (root.nodeType !== 1)\n return [];\n const visible = body === "true";\n return isElementVisible(root) === visible ? [root] : [];\n };\n return { queryAll };\n }\n _createInternalChainEngine() {\n const queryAll = (root, body) => {\n return this.querySelectorAll(body.parsed, root);\n };\n return { queryAll };\n }\n extend(source, params) {\n const constrFunction = this.window.eval(`\n (() => {\n const module = {};\n ${source}\n return module.exports.default();\n })()`);\n return new constrFunction(this, params);\n }\n async viewportRatio(element) {\n return await new Promise((resolve) => {\n const observer = new IntersectionObserver((entries) => {\n resolve(entries[0].intersectionRatio);\n observer.disconnect();\n });\n observer.observe(element);\n this.utils.builtins.requestAnimationFrame(() => {\n });\n });\n }\n getElementBorderWidth(node) {\n if (node.nodeType !== Node.ELEMENT_NODE || !node.ownerDocument || !node.ownerDocument.defaultView)\n return { left: 0, top: 0 };\n const style = node.ownerDocument.defaultView.getComputedStyle(node);\n return { left: parseInt(style.borderLeftWidth || "", 10), top: parseInt(style.borderTopWidth || "", 10) };\n }\n describeIFrameStyle(iframe) {\n if (!iframe.ownerDocument || !iframe.ownerDocument.defaultView)\n return "error:notconnected";\n const defaultView = iframe.ownerDocument.defaultView;\n for (let e = iframe; e; e = parentElementOrShadowHost(e)) {\n if (defaultView.getComputedStyle(e).transform !== "none")\n return "transformed";\n }\n const iframeStyle = defaultView.getComputedStyle(iframe);\n return {\n left: parseInt(iframeStyle.borderLeftWidth || "", 10) + parseInt(iframeStyle.paddingLeft || "", 10),\n top: parseInt(iframeStyle.borderTopWidth || "", 10) + parseInt(iframeStyle.paddingTop || "", 10)\n };\n }\n retarget(node, behavior) {\n let element = node.nodeType === Node.ELEMENT_NODE ? node : node.parentElement;\n if (!element)\n return null;\n if (behavior === "none")\n return element;\n if (!element.matches("input, textarea, select") && !element.isContentEditable) {\n if (behavior === "button-link")\n element = element.closest("button, [role=button], a, [role=link]") || element;\n else\n element = element.closest("button, [role=button], [role=checkbox], [role=radio]") || element;\n }\n if (behavior === "follow-label") {\n if (!element.matches("a, input, textarea, button, select, [role=link], [role=button], [role=checkbox], [role=radio]") && !element.isContentEditable) {\n const enclosingLabel = element.closest("label");\n if (enclosingLabel && enclosingLabel.control)\n element = enclosingLabel.control;\n }\n }\n return element;\n }\n async checkElementStates(node, states) {\n if (states.includes("stable")) {\n const stableResult = await this._checkElementIsStable(node);\n if (stableResult === false)\n return { missingState: "stable" };\n if (stableResult === "error:notconnected")\n return "error:notconnected";\n }\n for (const state of states) {\n if (state !== "stable") {\n const result = this.elementState(node, state);\n if (result.received === "error:notconnected")\n return "error:notconnected";\n if (!result.matches)\n return { missingState: state };\n }\n }\n }\n async _checkElementIsStable(node) {\n const continuePolling = Symbol("continuePolling");\n let lastRect;\n let stableRafCounter = 0;\n let lastTime = 0;\n const check = () => {\n const element = this.retarget(node, "no-follow-label");\n if (!element)\n return "error:notconnected";\n const time = this.utils.builtins.performance.now();\n if (this._stableRafCount > 1 && time - lastTime < 15)\n return continuePolling;\n lastTime = time;\n const clientRect = element.getBoundingClientRect();\n const rect = { x: clientRect.top, y: clientRect.left, width: clientRect.width, height: clientRect.height };\n if (lastRect) {\n const samePosition = rect.x === lastRect.x && rect.y === lastRect.y && rect.width === lastRect.width && rect.height === lastRect.height;\n if (!samePosition)\n return false;\n if (++stableRafCounter >= this._stableRafCount)\n return true;\n }\n lastRect = rect;\n return continuePolling;\n };\n let fulfill;\n let reject;\n const result = new Promise((f, r) => {\n fulfill = f;\n reject = r;\n });\n const raf = () => {\n try {\n const success = check();\n if (success !== continuePolling)\n fulfill(success);\n else\n this.utils.builtins.requestAnimationFrame(raf);\n } catch (e) {\n reject(e);\n }\n };\n this.utils.builtins.requestAnimationFrame(raf);\n return result;\n }\n _createAriaRefEngine() {\n const queryAll = (root, selector) => {\n var _a, _b;\n const result = (_b = (_a = this._lastAriaSnapshotForQuery) == null ? void 0 : _a.elements) == null ? void 0 : _b.get(selector);\n return result && result.isConnected ? [result] : [];\n };\n return { queryAll };\n }\n elementState(node, state) {\n const element = this.retarget(node, ["visible", "hidden"].includes(state) ? "none" : "follow-label");\n if (!element || !element.isConnected) {\n if (state === "hidden")\n return { matches: true, received: "hidden" };\n return { matches: false, received: "error:notconnected" };\n }\n if (state === "visible" || state === "hidden") {\n const visible = isElementVisible(element);\n return {\n matches: state === "visible" ? visible : !visible,\n received: visible ? "visible" : "hidden"\n };\n }\n if (state === "disabled" || state === "enabled") {\n const disabled = getAriaDisabled(element);\n return {\n matches: state === "disabled" ? disabled : !disabled,\n received: disabled ? "disabled" : "enabled"\n };\n }\n if (state === "editable") {\n const disabled = getAriaDisabled(element);\n const readonly = getReadonly(element);\n if (readonly === "error")\n throw this.createStacklessError("Element is not an
${escapeHTML(options.description)}
` : ""; + const styleSheet = ` + @keyframes pw-chapter-fade-in { + from { opacity: 0; } + to { opacity: 1; } + } + @keyframes pw-chapter-fade-out { + from { opacity: 1; } + to { opacity: 0; } + } + #background { + position: absolute; + inset: 0; + display: flex; + align-items: center; + justify-content: center; + backdrop-filter: blur(2px); + animation: pw-chapter-fade-in ${fadeDuration}ms ease-out forwards; + } + #background.fade-out { + animation: pw-chapter-fade-out ${fadeDuration}ms ease-in forwards; + } + #content { + background: rgba(0, 0, 0, 0.7); + border: 1px solid rgba(255, 255, 255, 0.15); + border-radius: 16px; + padding: 40px 56px; + max-width: 560px; + box-shadow: 0 8px 32px rgba(0, 0, 0, 0.4); + } + #title { + color: white; + font-family: system-ui, -apple-system, sans-serif; + font-size: 28px; + font-weight: 600; + line-height: 1.3; + text-align: center; + letter-spacing: -0.01em; + } + #description { + color: rgba(255, 255, 255, 0.7); + font-family: system-ui, -apple-system, sans-serif; + font-size: 15px; + line-height: 1.5; + margin-top: 12px; + text-align: center; + } + `; + const duration = options.duration ?? 2e3; + const html = `
${escapeHTML(options.title)}
${descriptionHtml}
`; + const id = await this.show(html); + await new Promise((f) => setTimeout(f, duration)); + const utility = await this._page.mainFrame().utilityContext(); + await utility.evaluate(({ injected, id: id2, fadeDuration: fadeDuration2 }) => { + const overlay = injected.getUserOverlay(id2); + const bg = overlay?.querySelector("#background"); + if (bg) + bg.classList.add("fade-out"); + return new Promise((f) => injected.utils.builtins.setTimeout(f, fadeDuration2)); + }, { injected: await utility.injectedScript(), id, fadeDuration }).catch((e) => debugLogger.log("error", e)); + await this.remove(id); + } + async setVisible(visible) { + if (!this._overlays.size) + return; + const utility = await this._page.mainFrame().utilityContext(); + await utility.evaluate(({ injected, visible: visible2 }) => { + injected.setUserOverlaysVisible(visible2); + }, { injected: await utility.injectedScript(), visible }).catch((e) => debugLogger.log("error", e)); + } + }; + } +}); + +// packages/playwright-core/src/server/screencast.ts +var Screencast; +var init_screencast = __esm({ + "packages/playwright-core/src/server/screencast.ts"() { + "use strict"; + init_manualPromise(); + init_protocolFormatter(); + init_debugLogger(); + init_progress(); + init_dom(); + Screencast = class { + constructor(page) { + this._clients = /* @__PURE__ */ new Map(); + this.page = page; + this.page.instrumentation.addListener(this, this.page.browserContext); + } + async handlePageOrContextClose() { + const clients = [...this._clients.keys()]; + this._clients.clear(); + for (const client of clients) { + if (client.gracefulClose) + await client.gracefulClose(); + } + } + dispose() { + for (const client of this._clients.keys()) + client.dispose(); + this._clients.clear(); + this.page.instrumentation.removeListener(this); + } + showActions(options) { + this._actions = options; + } + hideActions() { + this._actions = void 0; + } + addClient(client) { + const isFirst = this._clients.size === 0; + this._clients.set(client, new ManualPromise()); + if (isFirst) { + this._startScreencast(client.size, client.quality); + } else if (this._lastFrame) { + const frame = this._lastFrame; + setTimeout(() => { + if (this._clients.has(client)) + void client.onFrame(frame); + }, 0); + } + return { size: this._size }; + } + removeClient(client) { + const disconnected = this._clients.get(client); + if (!disconnected) + return; + this._clients.delete(client); + disconnected.resolve(); + if (!this._clients.size) + this._stopScreencast(); + } + _startScreencast(size, quality) { + this._size = size; + if (!this._size) { + const viewport = this.page.browserContext._options.viewport || { width: 800, height: 600 }; + const scale = Math.min(1, 800 / Math.max(viewport.width, viewport.height)); + this._size = { + width: Math.floor(viewport.width * scale), + height: Math.floor(viewport.height * scale) + }; + } + this._size = { + width: this._size.width & ~1, + height: this._size.height & ~1 + }; + this.page.delegate.startScreencast({ + width: this._size.width, + height: this._size.height, + quality: quality ?? 90 + }); + } + _stopScreencast() { + this._lastFrame = void 0; + this.page.delegate.stopScreencast(); + } + onScreencastFrame(frame, ack) { + this._lastFrame = frame; + const asyncResults = []; + for (const [client, disconnected] of this._clients) { + const result2 = client.onFrame(frame); + if (!result2) + continue; + asyncResults.push(Promise.race([result2.catch(() => { + }), disconnected])); + } + if (ack) { + if (!asyncResults.length) + ack(); + else + Promise.race(asyncResults).then(ack); + } + } + async onBeforeInputAction(sdkObject, metadata, point, box) { + if (!this._actions) + return; + const page = sdkObject.attribution.page; + if (page !== this.page) + return; + if (!box && sdkObject instanceof ElementHandle) + box = await sdkObject.boundingBox(nullProgress) || void 0; + const actionTitle2 = renderTitleForCall(metadata); + const utility = await page.mainFrame().utilityContext(); + await utility.evaluate(async (options) => { + const { injected, duration } = options; + injected.setScreencastAnnotation(options); + await new Promise((f) => injected.utils.builtins.setTimeout(f, duration)); + injected.setScreencastAnnotation(null); + }, { + injected: await utility.injectedScript(), + duration: this._actions?.duration ?? 500, + point, + box, + actionTitle: actionTitle2, + position: this._actions?.position, + fontSize: this._actions?.fontSize, + cursor: this._actions?.cursor ?? "pointer" + }).catch((e) => debugLogger.log("error", e)); + } + }; + } +}); + +// packages/playwright-core/src/server/page.ts +async function ariaSnapshotForFrame(progress2, frame, options = {}) { + const snapshot3 = await frame.retryWithProgressAndTimeouts(progress2, [1e3, 2e3, 4e3, 8e3], async (progress3, continuePolling) => { + try { + const context2 = await progress3.race(frame.utilityContext()); + const injectedScript = await progress3.race(context2.injectedScript()); + const snapshotOrRetry = await progress3.race(injectedScript.evaluate((injected, options2) => { + if (options2.info) { + const element2 = injected.querySelector(options2.info.parsed, injected.document, options2.info.strict); + if (!element2) + return false; + return injected.incrementalAriaSnapshot(element2, options2); + } + const node = injected.document.body; + if (!node) + return true; + return injected.incrementalAriaSnapshot(node, options2); + }, { + mode: options.mode ?? "default", + refPrefix: frame.seq ? "f" + frame.seq : "", + track: options.track, + doNotRenderActive: options.doNotRenderActive, + info: options.info, + depth: options.depth, + boxes: options.boxes + })); + if (snapshotOrRetry === true) + return continuePolling; + if (snapshotOrRetry === false) + throw new NonRecoverableDOMError(`Selector "${stringifySelector(options.info.parsed)}" does not match any element`); + return snapshotOrRetry; + } catch (e) { + if (frame.isNonRetriableError(e)) + throw e; + return continuePolling; + } + }); + const renderedIframeRefs = snapshot3.iframeRefs.filter((ref) => ref in snapshot3.iframeDepths); + progress2.setAllowConcurrentOrNestedRaces(true); + const childSnapshotPromises = renderedIframeRefs.map((ref) => { + const iframeDepth = snapshot3.iframeDepths[ref]; + const childDepth = options.depth ? options.depth - iframeDepth - 1 : void 0; + return ariaSnapshotFrameRef(progress2, frame, ref, { ...options, depth: childDepth }); + }); + const childSnapshots = await Promise.all(childSnapshotPromises); + progress2.setAllowConcurrentOrNestedRaces(false); + const full = []; + let incremental; + if (snapshot3.incremental !== void 0) { + incremental = snapshot3.incremental.split("\n"); + for (let i = 0; i < renderedIframeRefs.length; i++) { + const childSnapshot = childSnapshots[i]; + if (childSnapshot.incremental) + incremental.push(...childSnapshot.incremental); + else if (childSnapshot.full.length) + incremental.push("- iframe [ref=" + renderedIframeRefs[i] + "]:", ...childSnapshot.full.map((l) => " " + l)); + } + } + for (const line of snapshot3.full.split("\n")) { + const match = line.match(/^(\s*)- iframe (?:\[active\] )?\[ref=([^\]]*)\]/); + if (!match) { + full.push(line); + continue; + } + const leadingSpace = match[1]; + const ref = match[2]; + const childSnapshot = childSnapshots[renderedIframeRefs.indexOf(ref)] ?? { full: [] }; + full.push(childSnapshot.full.length ? line + ":" : line); + full.push(...childSnapshot.full.map((l) => leadingSpace + " " + l)); + } + return { full, incremental }; +} +async function ariaSnapshotFrameRef(progress2, parentFrame, frameRef, options) { + const frameSelector = `aria-ref=${frameRef} >> internal:control=enter-frame`; + const frameBodySelector = `${frameSelector} >> body`; + const child = await progress2.race(parentFrame.selectors.resolveFrameForSelector(frameBodySelector, { strict: true })); + if (!child) + return { full: [] }; + try { + return await ariaSnapshotForFrame(progress2, child.frame, { ...options, info: void 0 }); + } catch { + return { full: [] }; + } +} +function ensureArrayLimit(array, limit) { + if (array.length > limit) + return array.splice(0, limit / 10); + return []; +} +var PageEvent, navigationMarkSymbol, Page, WorkerEvent, Worker, PageBinding, InitScript; +var init_page = __esm({ + "packages/playwright-core/src/server/page.ts"() { + "use strict"; + init_selectorParser(); + init_manualPromise(); + init_utilityScriptSerializers(); + init_comparators(); + init_debugLogger(); + init_manualPromise(); + init_assert(); + init_stringUtils(); + init_locatorGenerators(); + init_browserContext(); + init_disposable2(); + init_console(); + init_errors(); + init_fileChooser(); + init_frames(); + init_helper(); + init_input(); + init_instrumentation(); + init_javascript(); + init_screenshotter(); + init_callLog(); + init_bindingsControllerSource(); + init_overlay(); + init_dom(); + init_screencast(); + init_javascript(); + PageEvent = { + Close: "close", + Crash: "crash", + Download: "download", + EmulatedSizeChanged: "emulatedsizechanged", + FileChooser: "filechooser", + FrameAttached: "frameattached", + FrameDetached: "framedetached", + InternalFrameNavigatedToNewDocument: "internalframenavigatedtonewdocument", + LocatorHandlerTriggered: "locatorhandlertriggered", + WebSocket: "websocket", + Worker: "worker" + }; + navigationMarkSymbol = Symbol("navigationMark"); + Page = class _Page extends SdkObject { + constructor(delegate, browserContext) { + super(browserContext, "page"); + this._closedState = "open"; + this.closedPromise = new ManualPromise(); + this._initializedPromise = new ManualPromise(); + this._consoleMessages = []; + this._pageErrors = []; + this._crashed = false; + this.openScope = new LongStandingScope(); + this._emulatedMedia = {}; + this._fileChooserInterceptedBy = /* @__PURE__ */ new Set(); + this._pageBindings = /* @__PURE__ */ new Map(); + this.initScripts = []; + this._workers = /* @__PURE__ */ new Map(); + this.requestInterceptors = []; + this._locatorHandlers = /* @__PURE__ */ new Map(); + this._lastLocatorHandlerUid = 0; + this._locatorHandlerRunningCounter = 0; + this._networkRequests = []; + this.attribution.page = this; + this.delegate = delegate; + this.browserContext = browserContext; + this.keyboard = new Keyboard(delegate.rawKeyboard, this); + this.mouse = new Mouse(delegate.rawMouse, this); + this.touchscreen = new Touchscreen(delegate.rawTouchscreen, this); + this.screenshotter = new Screenshotter(this); + this.frameManager = new FrameManager(this); + this.overlay = new Overlay(this); + this.screencast = new Screencast(this); + if (delegate.pdf) + this.pdf = delegate.pdf.bind(delegate); + this.coverage = delegate.coverage ? delegate.coverage() : null; + this.isStorageStatePage = browserContext.isCreatingStorageStatePage(); + } + static { + this.Events = PageEvent; + } + async reportAsNew(opener, error) { + if (this.delegate.noUtilityWorld?.()) { + await this._addInitScript(saveGlobalsSnapshotSource); + await this.safeNonStallingEvaluateInAllFrames(saveGlobalsSnapshotSource, "main"); + } + if (opener) { + const openerPageOrError = await opener.waitForInitializedOrError(); + if (openerPageOrError instanceof _Page && !openerPageOrError.isClosed()) + this._opener = openerPageOrError; + } + this._markInitialized(error); + } + _markInitialized(error = void 0) { + if (error) { + if (this.browserContext.isClosingOrClosed()) + return; + this.frameManager.createDummyMainFrameIfNeeded(); + } + this._initialized = error || this; + this.emitOnContext(BrowserContext.Events.Page, this); + for (const pageError of this._pageErrors) + this.emitOnContext(BrowserContext.Events.PageError, pageError, this); + for (const message of this._consoleMessages) + this.emitOnContext(BrowserContext.Events.Console, message); + if (this.isClosed()) + this.emit(_Page.Events.Close); + else + this.instrumentation.onPageOpen(this); + this._initializedPromise.resolve(this._initialized); + } + initializedOrUndefined() { + return this._initialized ? this : void 0; + } + waitForInitializedOrError() { + return this._initializedPromise; + } + emitOnContext(event, ...args) { + if (this.isStorageStatePage) + return; + this.browserContext.emit(event, ...args); + } + async resetForReuse(progress2) { + await this.mainFrame().gotoImpl(progress2, "about:blank", {}); + this._emulatedSize = void 0; + this._emulatedMedia = {}; + this._extraHTTPHeaders = void 0; + await progress2.race(Promise.all([ + this.delegate.updateEmulatedViewportSize(), + this.delegate.updateEmulateMedia(), + this.delegate.updateExtraHTTPHeaders() + ])); + await this.delegate.resetForReuse(progress2); + } + _didClose() { + this.frameManager.dispose(); + this.screencast.dispose(); + this.overlay.dispose(); + assert(this._closedState !== "closed", "Page closed twice"); + this._closedState = "closed"; + this.emit(_Page.Events.Close); + this.browserContext.emit(BrowserContext.Events.PageClosed, this); + this.closedPromise.resolve(); + this.instrumentation.onPageClose(this); + this.openScope.close(new TargetClosedError(this.closeReason())); + } + _didCrash() { + this.frameManager.dispose(); + this.screencast.dispose(); + this.overlay.dispose(); + this.emit(_Page.Events.Crash); + this._crashed = true; + this.instrumentation.onPageClose(this); + this.openScope.close(new Error("Page crashed")); + } + async _onFileChooserOpened(handle) { + let multiple; + try { + multiple = await handle.evaluate((element2) => !!element2.multiple); + } catch (e) { + return; + } + if (!this.listenerCount(_Page.Events.FileChooser)) { + handle.dispose(); + return; + } + const fileChooser = new FileChooser(handle, multiple); + this.emit(_Page.Events.FileChooser, fileChooser); + } + opener() { + return this._opener; + } + mainFrame() { + return this.frameManager.mainFrame(); + } + frames() { + return this.frameManager.frames(); + } + async exposeBinding(progress2, name, playwrightBinding) { + if (this._pageBindings.has(name)) + throw new Error(`Function "${name}" has been already registered`); + if (this.browserContext._pageBindings.has(name)) + throw new Error(`Function "${name}" has been already registered in the browser context`); + await progress2.race(this.browserContext.exposePlaywrightBindingIfNeeded()); + const binding = new PageBinding(this, name, playwrightBinding); + this._pageBindings.set(name, binding); + try { + await progress2.race(this.delegate.addInitScript(binding.initScript)); + await progress2.race(this.safeNonStallingEvaluateInAllFrames(binding.initScript.source, "main")); + return binding; + } catch (error) { + this._pageBindings.delete(name); + throw error; + } + } + async removeExposedBinding(binding) { + if (this._pageBindings.get(binding.name) !== binding) + return; + this._pageBindings.delete(binding.name); + await this.delegate.removeInitScripts([binding.initScript]); + const cleanup = `{ ${binding.cleanupScript} };`; + await this.safeNonStallingEvaluateInAllFrames(cleanup, "main"); + } + async setExtraHTTPHeaders(progress2, headers) { + const oldHeaders = this._extraHTTPHeaders; + try { + this._extraHTTPHeaders = headers; + await progress2.race(this.delegate.updateExtraHTTPHeaders()); + } catch (error) { + this._extraHTTPHeaders = oldHeaders; + this.delegate.updateExtraHTTPHeaders().catch(() => { + }); + throw error; + } + } + extraHTTPHeaders() { + return this._extraHTTPHeaders; + } + addNetworkRequest(request2) { + this._networkRequests.push(request2); + ensureArrayLimit(this._networkRequests, 100); + } + networkRequests() { + return this._networkRequests; + } + async onBindingCalled(payload, context2) { + if (this._closedState === "closed") + return; + await PageBinding.dispatch(this, payload, context2); + } + addConsoleMessage(worker, type3, args, location2, text2, timestamp) { + const message = new ConsoleMessage(this, worker, type3, text2, args, location2, timestamp); + const intercepted = this.frameManager.interceptConsoleMessage(message); + if (intercepted) { + args.forEach((arg) => arg.dispose()); + return; + } + this._consoleMessages.push(message); + ensureArrayLimit(this._consoleMessages, 200); + if (this._initialized) + this.emitOnContext(BrowserContext.Events.Console, message); + } + clearConsoleMessages() { + this._consoleMessages.length = 0; + } + consoleMessages(filter) { + if (filter === "all") + return this._consoleMessages; + const marked = this._consoleMessages.findLastIndex((m) => m[navigationMarkSymbol]); + return marked === -1 ? this._consoleMessages : this._consoleMessages.slice(marked + 1); + } + addPageError(error, location2) { + const pageError = { error, location: location2 }; + this._pageErrors.push(pageError); + ensureArrayLimit(this._pageErrors, 200); + if (this._initialized) + this.emitOnContext(BrowserContext.Events.PageError, pageError, this); + } + clearPageErrors() { + this._pageErrors.length = 0; + } + pageErrors(filter) { + if (filter === "all") + return this._pageErrors.map((e) => e.error); + const marked = this._pageErrors.findLastIndex((e) => e[navigationMarkSymbol]); + return (marked === -1 ? this._pageErrors : this._pageErrors.slice(marked + 1)).map((e) => e.error); + } + async reload(progress2, options) { + return this.mainFrame().raceNavigationAction(progress2, async () => { + const [response2] = await Promise.all([ + // Reload must be a new document, and should not be confused with a stray pushState. + this.mainFrame().waitForNavigation(progress2, true, options), + progress2.race(this.delegate.reload()) + ]); + return response2; + }); + } + async goBack(progress2, options) { + return this.mainFrame().raceNavigationAction(progress2, async () => { + let error; + const waitPromise = this.mainFrame().waitForNavigation(progress2, false, options).catch((e) => { + error = e; + return null; + }); + const result2 = await progress2.race(this.delegate.goBack()); + if (!result2) { + waitPromise.catch(() => { + }); + return null; + } + const response2 = await waitPromise; + if (error) + throw error; + return response2; + }); + } + async goForward(progress2, options) { + return this.mainFrame().raceNavigationAction(progress2, async () => { + let error; + const waitPromise = this.mainFrame().waitForNavigation(progress2, false, options).catch((e) => { + error = e; + return null; + }); + const result2 = await progress2.race(this.delegate.goForward()); + if (!result2) { + waitPromise.catch(() => { + }); + return null; + } + const response2 = await waitPromise; + if (error) + throw error; + return response2; + }); + } + requestGC(progress2) { + return progress2.race(this.delegate.requestGC()); + } + registerLocatorHandler(selector, noWaitAfter) { + const uid = ++this._lastLocatorHandlerUid; + this._locatorHandlers.set(uid, { selector, noWaitAfter }); + return uid; + } + resolveLocatorHandler(uid, remove) { + const handler = this._locatorHandlers.get(uid); + if (remove) + this._locatorHandlers.delete(uid); + if (handler) { + handler.resolved?.resolve(); + handler.resolved = void 0; + } + } + unregisterLocatorHandler(uid) { + this._locatorHandlers.delete(uid); + } + async performActionPreChecks(progress2) { + await this._performWaitForNavigationCheck(progress2); + await this._performLocatorHandlersCheckpoint(progress2); + await this._performWaitForNavigationCheck(progress2); + } + async _performWaitForNavigationCheck(progress2) { + if (process.env.PLAYWRIGHT_SKIP_NAVIGATION_CHECK) + return; + const mainFrame = this.frameManager.mainFrame(); + if (!mainFrame || !mainFrame.pendingDocument()) + return; + const url2 = mainFrame.pendingDocument()?.request?.url(); + const toUrl = url2 ? `" ${trimStringWithEllipsis(url2, 200)}"` : ""; + progress2.log(` waiting for${toUrl} navigation to finish...`); + await helper.waitForEvent(progress2, mainFrame, Frame.Events.InternalNavigation, (e) => { + if (!e.isPublic) + return false; + if (!e.error) + progress2.log(` navigated to "${trimStringWithEllipsis(mainFrame.url(), 200)}"`); + return true; + }).promise; + } + async _performLocatorHandlersCheckpoint(progress2) { + if (this._locatorHandlerRunningCounter) + return; + for (const [uid, handler] of this._locatorHandlers) { + if (!handler.resolved) { + if (await this.mainFrame().isVisibleInternal(progress2, handler.selector, { strict: true })) { + handler.resolved = new ManualPromise(); + this.emit(_Page.Events.LocatorHandlerTriggered, uid); + } + } + if (handler.resolved) { + ++this._locatorHandlerRunningCounter; + progress2.log(` found ${asLocator(this.browserContext._browser.sdkLanguage(), handler.selector)}, intercepting action to run the handler`); + const promise = handler.resolved.then(async () => { + if (!handler.noWaitAfter) { + progress2.log(` locator handler has finished, waiting for ${asLocator(this.browserContext._browser.sdkLanguage(), handler.selector)} to be hidden`); + await this.mainFrame().waitForSelector(progress2, handler.selector, false, { state: "hidden" }); + } else { + progress2.log(` locator handler has finished`); + } + }); + try { + progress2.setAllowConcurrentOrNestedRaces(true); + await progress2.race(this.openScope.race(promise)); + } finally { + progress2.setAllowConcurrentOrNestedRaces(false); + --this._locatorHandlerRunningCounter; + } + progress2.log(` interception handler has finished, continuing`); + } + } + } + async emulateMedia(progress2, options) { + const oldEmulatedMedia = { ...this._emulatedMedia }; + if (options.media !== void 0) + this._emulatedMedia.media = options.media; + if (options.colorScheme !== void 0) + this._emulatedMedia.colorScheme = options.colorScheme; + if (options.reducedMotion !== void 0) + this._emulatedMedia.reducedMotion = options.reducedMotion; + if (options.forcedColors !== void 0) + this._emulatedMedia.forcedColors = options.forcedColors; + if (options.contrast !== void 0) + this._emulatedMedia.contrast = options.contrast; + try { + await progress2.race(this.delegate.updateEmulateMedia()); + } catch (error) { + this._emulatedMedia = oldEmulatedMedia; + this.delegate.updateEmulateMedia().catch(() => { + }); + throw error; + } + } + emulatedMedia() { + const contextOptions = this.browserContext._options; + return { + media: this._emulatedMedia.media || "no-override", + colorScheme: this._emulatedMedia.colorScheme !== void 0 ? this._emulatedMedia.colorScheme : contextOptions.colorScheme ?? "light", + reducedMotion: this._emulatedMedia.reducedMotion !== void 0 ? this._emulatedMedia.reducedMotion : contextOptions.reducedMotion ?? "no-preference", + forcedColors: this._emulatedMedia.forcedColors !== void 0 ? this._emulatedMedia.forcedColors : contextOptions.forcedColors ?? "none", + contrast: this._emulatedMedia.contrast !== void 0 ? this._emulatedMedia.contrast : contextOptions.contrast ?? "no-preference" + }; + } + async setViewportSize(progress2, viewportSize) { + const oldEmulatedSize = this._emulatedSize; + try { + this._setEmulatedSize({ viewport: { ...viewportSize }, screen: { ...viewportSize } }); + await progress2.race(this.delegate.updateEmulatedViewportSize()); + } catch (error) { + this._emulatedSize = oldEmulatedSize; + this.delegate.updateEmulatedViewportSize().catch(() => { + }); + throw error; + } + } + setEmulatedSizeFromWindowOpen(emulatedSize) { + this._setEmulatedSize(emulatedSize); + } + _setEmulatedSize(emulatedSize) { + this._emulatedSize = emulatedSize; + this.emit(_Page.Events.EmulatedSizeChanged); + } + emulatedSize() { + if (this._emulatedSize) + return this._emulatedSize; + const contextOptions = this.browserContext._options; + return contextOptions.viewport ? { viewport: contextOptions.viewport, screen: contextOptions.screen || contextOptions.viewport } : void 0; + } + async bringToFront(progress2) { + await progress2.race(this.delegate.bringToFront()); + } + async addInitScript(progress2, source11) { + return await progress2.race(this._addInitScript(source11)); + } + async _addInitScript(source11) { + const initScript = new InitScript(this, source11); + this.initScripts.push(initScript); + try { + await this.delegate.addInitScript(initScript); + } catch (error) { + initScript.dispose().catch(() => { + }); + throw error; + } + return initScript; + } + async removeInitScript(initScript) { + this.initScripts = this.initScripts.filter((script) => initScript !== script); + await this.delegate.removeInitScripts([initScript]); + } + needsRequestInterception() { + return this.requestInterceptors.length > 0 || this.browserContext.requestInterceptors.length > 0; + } + async addRequestInterceptor(progress2, handler, prepend) { + if (prepend) + this.requestInterceptors.unshift(handler); + else + this.requestInterceptors.push(handler); + await progress2.race(this.delegate.updateRequestInterception()); + } + async removeRequestInterceptor(handler) { + const index = this.requestInterceptors.indexOf(handler); + if (index === -1) + return; + this.requestInterceptors.splice(index, 1); + await this.browserContext.notifyRoutesInFlightAboutRemovedHandler(handler); + await this.delegate.updateRequestInterception(); + } + async expectScreenshot(progress2, options) { + const locator2 = options.locator; + const rafrafScreenshot = locator2 ? async (progress3, timeout) => { + return await locator2.frame.rafrafTimeoutScreenshotElementWithProgress(progress3, locator2.selector, timeout, options || {}); + } : async (progress3, timeout) => { + await this.performActionPreChecks(progress3); + await this.mainFrame().rafrafTimeout(progress3, timeout); + return await this.screenshotter.screenshotPage(progress3, options || {}); + }; + const comparator = getComparator("image/png"); + let intermediateResult; + const areEqualScreenshots = (actual, expected, previous) => { + const comparatorResult = actual && expected ? comparator(actual, expected, options) : void 0; + if (comparatorResult !== void 0 && !!comparatorResult === !!options.isNot) + return true; + if (comparatorResult) + intermediateResult = { errorMessage: comparatorResult.errorMessage, diff: comparatorResult.diff, actual, previous }; + return false; + }; + try { + if (!options.expected && options.isNot) + throw new Error('"not" matcher requires expected result'); + const format2 = validateScreenshotOptions(options || {}); + if (format2 !== "png") + throw new Error("Only PNG screenshots are supported"); + let actual; + let previous; + const pollIntervals = [0, 100, 250, 500]; + if (options.expected) + progress2.log(` verifying given screenshot expectation`); + else + progress2.log(` generating new stable screenshot expectation`); + let isFirstIteration = true; + while (true) { + if (this.isClosed()) + throw new Error("The page has closed"); + const screenshotTimeout = pollIntervals.shift() ?? 1e3; + if (screenshotTimeout) + progress2.log(`waiting ${screenshotTimeout}ms before taking screenshot`); + previous = actual; + actual = await rafrafScreenshot(progress2, screenshotTimeout).catch((e) => { + if (this.mainFrame().isNonRetriableError(e)) + throw e; + progress2.log(`failed to take screenshot - ` + e.message); + return void 0; + }); + if (!actual) + continue; + const expectation = options.expected && isFirstIteration ? options.expected : previous; + if (areEqualScreenshots(actual, expectation, previous)) + break; + if (intermediateResult) + progress2.log(intermediateResult.errorMessage); + isFirstIteration = false; + } + if (!isFirstIteration) + progress2.log(`captured a stable screenshot`); + if (!options.expected) + return { actual }; + if (isFirstIteration) { + progress2.log(`screenshot matched expectation`); + return {}; + } + if (areEqualScreenshots(actual, options.expected, void 0)) { + progress2.log(`screenshot matched expectation`); + return {}; + } + throw new Error(intermediateResult.errorMessage); + } catch (e) { + if (isJavaScriptErrorInEvaluate(e) || isInvalidSelectorError(e)) + throw e; + let errorMessage = e.message; + if (e instanceof TimeoutError && intermediateResult?.previous) + errorMessage = `Failed to take two consecutive stable screenshots.`; + const details = { + log: compressCallLog(e.message ? [...progress2.metadata.log, e.message] : progress2.metadata.log), + actual: intermediateResult?.actual, + previous: intermediateResult?.previous, + diff: intermediateResult?.diff, + timedOut: e instanceof TimeoutError, + customErrorMessage: errorMessage + }; + const error = new Error("Expect failed"); + error.details = details; + throw error; + } + } + async screenshot(progress2, options) { + return await this.screenshotter.screenshotPage(progress2, options); + } + async close(progress2, options = {}) { + await progress2.race(this._close(options)); + } + async _close(options = {}) { + if (this._closedState === "closed") + return; + if (options.reason) + this._closeReason = options.reason; + await this.screencast.handlePageOrContextClose(); + if (this._closedState !== "closing") { + this._closedState = "closing"; + await this.delegate.closePage(false).catch((e) => debugLogger.log("error", e)); + } + await this.closedPromise; + } + async runBeforeUnload(progress2) { + await progress2.race(this._runBeforeUnload()); + } + async _runBeforeUnload() { + await this.delegate.closePage(true).catch((e) => debugLogger.log("error", e)); + } + isClosed() { + return this._closedState === "closed"; + } + hasCrashed() { + return this._crashed; + } + isClosedOrClosingOrCrashed() { + return this._closedState !== "open" || this._crashed; + } + addWorker(workerId, worker) { + this._workers.set(workerId, worker); + this.emit(_Page.Events.Worker, worker); + } + removeWorker(workerId) { + const worker = this._workers.get(workerId); + if (!worker) + return; + worker.didClose(); + this._workers.delete(workerId); + } + clearWorkers() { + for (const [workerId, worker] of this._workers) { + worker.didClose(); + this._workers.delete(workerId); + } + } + async setFileChooserInterceptedBy(progress2, enabled, by) { + await progress2.race(this._setFileChooserInterceptedBy(enabled, by)); + } + async _setFileChooserInterceptedBy(enabled, by) { + const wasIntercepted = this.fileChooserIntercepted(); + if (enabled) + this._fileChooserInterceptedBy.add(by); + else + this._fileChooserInterceptedBy.delete(by); + if (wasIntercepted !== this.fileChooserIntercepted()) + await this.delegate.updateFileChooserInterception(); + } + fileChooserIntercepted() { + return this._fileChooserInterceptedBy.size > 0; + } + frameNavigatedToNewDocument(frame) { + this.emit(_Page.Events.InternalFrameNavigatedToNewDocument, frame); + this.browserContext.emit(BrowserContext.Events.InternalFrameNavigatedToNewDocument, frame); + const origin = frame.origin(); + if (origin) + this.browserContext.addVisitedOrigin(origin); + if (frame === this.mainFrame()) { + if (this._consoleMessages.length > 0) + this._consoleMessages[this._consoleMessages.length - 1][navigationMarkSymbol] = true; + if (this._pageErrors.length > 0) + this._pageErrors[this._pageErrors.length - 1][navigationMarkSymbol] = true; + } + } + allInitScripts() { + const bindings = [...this.browserContext._pageBindings.values(), ...this._pageBindings.values()].map((binding) => binding.initScript); + if (this.browserContext.bindingsInitScript) + bindings.unshift(this.browserContext.bindingsInitScript); + return [...bindings, ...this.browserContext.initScripts, ...this.initScripts]; + } + getBinding(name) { + return this._pageBindings.get(name) || this.browserContext._pageBindings.get(name); + } + async safeNonStallingEvaluateInAllFrames(expression2, world, options = {}) { + await Promise.all(this.frames().map(async (frame) => { + try { + await frame.nonStallingEvaluateInExistingContext(expression2, world); + } catch (e) { + if (options.throwOnJSErrors && isJavaScriptErrorInEvaluate(e)) + throw e; + } + })); + } + async hideHighlight() { + await Promise.all(this.frames().map((frame) => frame.hideHighlight().catch(() => { + }))); + } + async setDockTile(image) { + await this.delegate.setDockTile(image); + } + async webStorageItems(progress2, kind) { + const storage = `${kind}Storage`; + return await this.mainFrame().evaluateExpression(progress2, `(() => { + const result = []; + for (let i = 0; i < ${storage}.length; i++) { + const name = ${storage}.key(i); + if (name !== null) + result.push({ name, value: ${storage}.getItem(name) ?? '' }); + } + return result; + })()`, { world: "utility" }); + } + async webStorageGetItem(progress2, kind, name) { + const value2 = await this.mainFrame().evaluateExpression(progress2, `${kind}Storage.getItem(${JSON.stringify(name)})`, { world: "utility" }); + return value2 === null ? void 0 : value2; + } + async webStorageSetItem(progress2, kind, name, value2) { + await this.mainFrame().evaluateExpression(progress2, `${kind}Storage.setItem(${JSON.stringify(name)}, ${JSON.stringify(value2)})`, { world: "utility" }); + } + async webStorageRemoveItem(progress2, kind, name) { + await this.mainFrame().evaluateExpression(progress2, `${kind}Storage.removeItem(${JSON.stringify(name)})`, { world: "utility" }); + } + async webStorageClear(progress2, kind) { + await this.mainFrame().evaluateExpression(progress2, `${kind}Storage.clear()`, { world: "utility" }); + } + }; + WorkerEvent = { + Console: "console", + Close: "close" + }; + Worker = class _Worker extends SdkObject { + constructor(parent, url2, onDisconnect) { + super(parent, "worker"); + this._executionContextPromise = new ManualPromise(); + this._workerScriptLoaded = false; + this.existingExecutionContext = null; + this.openScope = new LongStandingScope(); + this.attribution.worker = this; + this.url = url2; + this._onDisconnect = onDisconnect; + } + static { + this.Events = WorkerEvent; + } + createExecutionContext(delegate) { + this.existingExecutionContext = new ExecutionContext(this, delegate, "worker"); + if (this._workerScriptLoaded) + this._executionContextPromise.resolve(this.existingExecutionContext); + return this.existingExecutionContext; + } + destroyExecutionContext(errorMessage) { + if (this.existingExecutionContext) + this.existingExecutionContext.contextDestroyed(errorMessage); + this.existingExecutionContext = null; + this._workerScriptLoaded = false; + this._executionContextPromise = new ManualPromise(); + } + workerScriptLoaded() { + this._workerScriptLoaded = true; + if (this.existingExecutionContext) + this._executionContextPromise.resolve(this.existingExecutionContext); + } + didClose() { + if (this.existingExecutionContext) + this.existingExecutionContext.contextDestroyed("Worker was closed"); + this.emit(_Worker.Events.Close, this); + this.openScope.close(new Error("Worker closed")); + } + async evaluateExpression(progress2, expression2, isFunction2, arg) { + return progress2.race(evaluateExpression(await this._executionContextPromise, expression2, { returnByValue: true, isFunction: isFunction2 }, arg)); + } + async evaluateExpressionHandle(progress2, expression2, isFunction2, arg) { + return progress2.race(evaluateExpression(await this._executionContextPromise, expression2, { returnByValue: false, isFunction: isFunction2 }, arg)); + } + async disconnect(progress2, options = {}) { + if (!this._onDisconnect) + throw new Error("Cannot disconnect from this worker"); + this._closeReason = options.reason; + await progress2.race(this._onDisconnect()); + } + }; + PageBinding = class _PageBinding extends DisposableObject { + static { + this.kController = "__playwright__binding__controller__"; + } + static { + this.kBindingName = "__playwright__binding__"; + } + static createInitScript(browserContext) { + return new InitScript(browserContext, ` + (() => { + const module = {}; + ${source5} + const property = '${_PageBinding.kController}'; + if (!globalThis[property]) + globalThis[property] = new (module.exports.BindingsController())(globalThis, '${_PageBinding.kBindingName}'); + })(); + `); + } + constructor(parent, name, playwrightFunction) { + super(parent); + this.name = name; + this.playwrightFunction = playwrightFunction; + this.initScript = new InitScript(parent, `globalThis['${_PageBinding.kController}'].addBinding(${JSON.stringify(name)})`); + this.cleanupScript = `globalThis['${_PageBinding.kController}'].removeBinding(${JSON.stringify(name)})`; + } + static async dispatch(page, payload, context2) { + const { name, seq, serializedArgs } = JSON.parse(payload); + try { + assert(context2.world); + const binding = page.getBinding(name); + if (!binding) + throw new Error(`Function "${name}" is not exposed`); + if (!Array.isArray(serializedArgs)) + throw new Error(`serializedArgs is not an array. This can happen when Array.prototype.toJSON is defined incorrectly`); + const args = serializedArgs.map((a) => parseEvaluationResultValue(a)); + const result2 = await binding.playwrightFunction({ frame: context2.frame, page, context: page.browserContext }, ...args); + context2.evaluateExpressionHandle(`arg => globalThis['${_PageBinding.kController}'].deliverBindingResult(arg)`, { isFunction: true }, { name, seq, result: result2 }).catch((e) => debugLogger.log("error", e)); + } catch (error) { + context2.evaluateExpressionHandle(`arg => globalThis['${_PageBinding.kController}'].deliverBindingResult(arg)`, { isFunction: true }, { name, seq, error }).catch((e) => debugLogger.log("error", e)); + } + } + async dispose() { + await this.parent.removeExposedBinding(this); + } + }; + InitScript = class extends DisposableObject { + constructor(owner, source11) { + super(owner); + this.source = `(() => { + ${source11} + })();`; + } + async dispose() { + await this.parent.removeInitScript(this); + } + }; + } +}); + +// packages/playwright-core/src/server/types.ts +var kLifecycleEvents; +var init_types = __esm({ + "packages/playwright-core/src/server/types.ts"() { + "use strict"; + kLifecycleEvents = /* @__PURE__ */ new Set(["load", "domcontentloaded", "networkidle", "commit"]); + } +}); + +// packages/playwright-core/src/server/frames.ts +function verifyLifecycle(name, waitUntil) { + if (waitUntil === "networkidle0") + waitUntil = "networkidle"; + if (!kLifecycleEvents.has(waitUntil)) + throw new Error(`${name}: expected one of (load|domcontentloaded|networkidle|commit)`); + return waitUntil; +} +function renderUnexpectedValue(expression2, received) { + if (expression2 === "to.match.aria") + return received ? received.raw : received; + return received; +} +var yaml, NavigationAbortedError, ExpectError, kDummyFrameId, FrameManager, FrameEvent, Frame, SignalBarrier; +var init_frames = __esm({ + "packages/playwright-core/src/server/frames.ts"() { + "use strict"; + init_ariaSnapshot(); + init_selectorParser(); + init_manualPromise(); + init_eventsHelper(); + init_manualPromise(); + init_locatorGenerators(); + init_assert(); + init_urlMatch(); + init_task(); + init_crypto(); + init_browserContext(); + init_dom(); + init_errors(); + init_fileUploadUtils(); + init_frameSelectors(); + init_helper(); + init_instrumentation(); + init_javascript(); + init_network2(); + init_page(); + init_progress(); + init_types(); + init_protocolError(); + yaml = require("./utilsBundle").yaml; + NavigationAbortedError = class extends Error { + constructor(documentId, message) { + super(message); + this.documentId = documentId; + } + }; + ExpectError = class extends Error { + constructor(details) { + super("Expect failed"); + this.name = "ExpectError"; + this.details = details; + } + }; + kDummyFrameId = ""; + FrameManager = class { + constructor(page) { + this._frames = /* @__PURE__ */ new Map(); + this._consoleMessageTags = /* @__PURE__ */ new Map(); + this._signalBarriers = /* @__PURE__ */ new Set(); + this._webSockets = /* @__PURE__ */ new Map(); + this._nextFrameSeq = 0; + this._page = page; + this._mainFrame = void 0; + } + _allocateFrameSeq() { + return this._nextFrameSeq++; + } + createDummyMainFrameIfNeeded() { + if (!this._mainFrame) + this.frameAttached(kDummyFrameId, null); + } + dispose() { + for (const frame of this._frames.values()) { + frame._stopNetworkIdleTimer(); + frame.invalidateNonStallingEvaluations("Target crashed"); + } + } + mainFrame() { + return this._mainFrame; + } + frames() { + const frames = []; + collect(this._mainFrame); + return frames; + function collect(frame) { + frames.push(frame); + for (const subframe of frame._getChildFrames()) + collect(subframe); + } + } + frame(frameId) { + return this._frames.get(frameId) || null; + } + frameAttached(frameId, parentFrameId) { + const parentFrame = parentFrameId ? this._frames.get(parentFrameId) : null; + if (!parentFrame) { + if (this._mainFrame) { + this._frames.delete(this._mainFrame._id); + this._mainFrame._id = frameId; + } else { + assert(!this._frames.has(frameId)); + this._mainFrame = new Frame(this._page, frameId, parentFrame); + } + this._frames.set(frameId, this._mainFrame); + return this._mainFrame; + } else { + assert(!this._frames.has(frameId)); + const frame = new Frame(this._page, frameId, parentFrame); + this._frames.set(frameId, frame); + this._page.emit(Page.Events.FrameAttached, frame); + this._page.browserContext.emit(BrowserContext.Events.FrameAttached, frame); + return frame; + } + } + async waitForSignalsCreatedBy(progress2, waitAfter, action) { + if (!waitAfter) + return action(progress2); + const barrier = new SignalBarrier(progress2); + this._signalBarriers.add(barrier); + try { + const result2 = await action(progress2); + await progress2.race(this._page.delegate.inputActionEpilogue()); + await barrier.waitFor(progress2); + await new Promise(makeWaitForNextTask()); + return result2; + } finally { + this._signalBarriers.delete(barrier); + } + } + frameWillPotentiallyRequestNavigation() { + for (const barrier of this._signalBarriers) + barrier.retain(); + } + frameDidPotentiallyRequestNavigation() { + for (const barrier of this._signalBarriers) + barrier.release(); + } + frameRequestedNavigation(frameId, documentId) { + const frame = this._frames.get(frameId); + if (!frame) + return; + for (const barrier of this._signalBarriers) + barrier.addFrameNavigation(frame); + if (frame.pendingDocument() && frame.pendingDocument().documentId === documentId) { + return; + } + const request2 = documentId ? Array.from(frame._inflightRequests).find((request3) => request3._documentId === documentId) : void 0; + frame._setPendingDocument({ documentId, request: request2 }); + } + frameCommittedNewDocumentNavigation(frameId, url2, name, documentId, initial) { + const frame = this._frames.get(frameId); + this.removeChildFramesRecursively(frame); + this._clearWebSockets(frame); + frame._url = url2; + frame._name = name; + let keepPending; + const pendingDocument = frame.pendingDocument(); + if (pendingDocument) { + if (pendingDocument.documentId === void 0) { + pendingDocument.documentId = documentId; + } + if (pendingDocument.documentId === documentId) { + frame._currentDocument = pendingDocument; + } else { + keepPending = pendingDocument; + frame._currentDocument = { documentId, request: void 0 }; + } + frame._setPendingDocument(void 0); + } else { + frame._currentDocument = { documentId, request: void 0 }; + } + frame._onClearLifecycle(); + const navigationEvent = { url: url2, name, newDocument: frame._currentDocument, isPublic: true }; + this._fireInternalFrameNavigation(frame, navigationEvent); + if (!initial) { + frame.apiLog(` navigated to "${url2}"`); + this._page.frameNavigatedToNewDocument(frame); + } + frame._setPendingDocument(keepPending); + } + frameCommittedSameDocumentNavigation(frameId, url2) { + const frame = this._frames.get(frameId); + if (!frame) + return; + const pending = frame.pendingDocument(); + if (pending && pending.documentId === void 0 && pending.request === void 0) { + frame._setPendingDocument(void 0); + } + frame._url = url2; + const navigationEvent = { url: url2, name: frame._name, isPublic: true }; + this._fireInternalFrameNavigation(frame, navigationEvent); + frame.apiLog(` navigated to "${url2}"`); + } + frameAbortedNavigation(frameId, errorText, documentId) { + const frame = this._frames.get(frameId); + if (!frame || !frame.pendingDocument()) + return; + if (documentId !== void 0 && frame.pendingDocument().documentId !== documentId) + return; + const navigationEvent = { + url: frame._url, + name: frame._name, + newDocument: frame.pendingDocument(), + error: new NavigationAbortedError(documentId, errorText), + isPublic: !(documentId && frame._redirectedNavigations.has(documentId)) + }; + frame._setPendingDocument(void 0); + this._fireInternalFrameNavigation(frame, navigationEvent); + } + frameDetached(frameId) { + const frame = this._frames.get(frameId); + if (frame) { + this._removeFramesRecursively(frame); + this._page.mainFrame()._recalculateNetworkIdle(); + } + } + frameLifecycleEvent(frameId, event) { + const frame = this._frames.get(frameId); + if (frame) + frame.onLifecycleEvent(event); + } + requestStarted(request2, route2) { + const frame = request2.frame(); + this._inflightRequestStarted(request2); + if (request2._documentId) + frame._setPendingDocument({ documentId: request2._documentId, request: request2 }); + if (request2._isFavicon) { + route2?.abort("aborted").catch(() => { + }); + return; + } + this._page.addNetworkRequest(request2); + this._page.emitOnContext(BrowserContext.Events.Request, request2); + if (route2) + new Route(request2, route2).handle([...this._page.requestInterceptors, ...this._page.browserContext.requestInterceptors]); + } + requestReceivedResponse(response2) { + if (response2.request()._isFavicon) + return; + this._page.emitOnContext(BrowserContext.Events.Response, response2); + } + reportRequestFinished(request2, response2) { + this._inflightRequestFinished(request2); + if (request2._isFavicon) + return; + this._page.emitOnContext(BrowserContext.Events.RequestFinished, { request: request2, response: response2 }); + } + requestFailed(request2, canceled) { + const frame = request2.frame(); + this._inflightRequestFinished(request2); + if (frame.pendingDocument() && frame.pendingDocument().request === request2) { + let errorText = request2.failure().errorText; + if (canceled) + errorText += "; maybe frame was detached?"; + this.frameAbortedNavigation(frame._id, errorText, frame.pendingDocument().documentId); + } + if (request2._isFavicon) + return; + this._page.emitOnContext(BrowserContext.Events.RequestFailed, request2); + } + removeChildFramesRecursively(frame) { + for (const child of frame._getChildFrames()) + this._removeFramesRecursively(child); + } + _removeFramesRecursively(frame) { + this.removeChildFramesRecursively(frame); + frame._onDetached(); + this._frames.delete(frame._id); + if (!this._page.isClosed()) + this._page.emit(Page.Events.FrameDetached, frame); + } + _inflightRequestFinished(request2) { + const frame = request2.frame(); + if (request2._isFavicon) + return; + if (!frame._inflightRequests.has(request2)) + return; + frame._inflightRequests.delete(request2); + if (frame._inflightRequests.size === 0) + frame._startNetworkIdleTimer(); + } + _inflightRequestStarted(request2) { + const frame = request2.frame(); + if (request2._isFavicon) + return; + frame._inflightRequests.add(request2); + if (frame._inflightRequests.size === 1) + frame._stopNetworkIdleTimer(); + } + interceptConsoleMessage(message) { + if (message.type() !== "debug") + return false; + const tag = message.text(); + const handler = this._consoleMessageTags.get(tag); + if (!handler) + return false; + this._consoleMessageTags.delete(tag); + handler(); + return true; + } + _clearWebSockets(frame) { + if (frame.parentFrame()) + return; + this._webSockets.clear(); + } + onWebSocketCreated(requestId, url2) { + const ws4 = new WebSocket(this._page, url2); + this._webSockets.set(requestId, ws4); + } + onWebSocketRequest(requestId, headers, wallTimeMs) { + const ws4 = this._webSockets.get(requestId); + if (!ws4) + return; + ws4.setWallTimeMs(wallTimeMs); + if (ws4.markAsNotified()) { + this._page.emit(Page.Events.WebSocket, ws4); + this._page.browserContext.emit(BrowserContext.Events.WebSocket, ws4, this._page); + } + ws4.requestSent(headers); + } + onWebSocketResponse(requestId, status, statusText2, headers) { + const ws4 = this._webSockets.get(requestId); + if (!ws4) + return; + ws4.responseReceived(status, statusText2, headers); + if (status >= 400) + ws4.error(`${statusText2}: ${status}`); + } + onWebSocketFrameSent(requestId, opcode, data, wallTimeMs) { + const ws4 = this._webSockets.get(requestId); + if (ws4) + ws4.frameSent(opcode, data, wallTimeMs); + } + webSocketFrameReceived(requestId, opcode, data, wallTimeMs) { + const ws4 = this._webSockets.get(requestId); + if (ws4) + ws4.frameReceived(opcode, data, wallTimeMs); + } + webSocketClosed(requestId) { + const ws4 = this._webSockets.get(requestId); + if (ws4) { + if (ws4.markAsNotified()) { + this._page.emit(Page.Events.WebSocket, ws4); + this._page.browserContext.emit(BrowserContext.Events.WebSocket, ws4, this._page); + } + ws4.closed(); + } + this._webSockets.delete(requestId); + } + webSocketError(requestId, errorMessage) { + const ws4 = this._webSockets.get(requestId); + if (ws4) { + if (ws4.markAsNotified()) { + this._page.emit(Page.Events.WebSocket, ws4); + this._page.browserContext.emit(BrowserContext.Events.WebSocket, ws4, this._page); + } + ws4.error(errorMessage); + } + } + _fireInternalFrameNavigation(frame, event) { + frame.emit(Frame.Events.InternalNavigation, event); + } + }; + FrameEvent = { + InternalNavigation: "internalnavigation", + AddLifecycle: "addlifecycle", + RemoveLifecycle: "removelifecycle" + }; + Frame = class _Frame extends SdkObject { + constructor(page, id, parentFrame) { + super(page, "frame"); + this._firedLifecycleEvents = /* @__PURE__ */ new Set(); + this._firedNetworkIdleSelf = false; + this._url = ""; + this._contextData = /* @__PURE__ */ new Map(); + this._childFrames = /* @__PURE__ */ new Set(); + this._name = ""; + this._inflightRequests = /* @__PURE__ */ new Set(); + this._detachedScope = new LongStandingScope(); + this._raceAgainstEvaluationStallingEventsPromises = /* @__PURE__ */ new Set(); + this._redirectedNavigations = /* @__PURE__ */ new Map(); + this.attribution.frame = this; + this.seq = page.frameManager._allocateFrameSeq(); + this._id = id; + this._page = page; + this._parentFrame = parentFrame; + this._currentDocument = { documentId: void 0, request: void 0 }; + this.selectors = new FrameSelectors(this); + this._contextData.set("main", { contextPromise: new ManualPromise(), context: null }); + this._contextData.set("utility", { contextPromise: new ManualPromise(), context: null }); + this._setContext("main", null); + this._setContext("utility", null); + if (this._parentFrame) + this._parentFrame._childFrames.add(this); + this._firedLifecycleEvents.add("commit"); + if (id !== kDummyFrameId) + this._startNetworkIdleTimer(); + } + static { + this.Events = FrameEvent; + } + _isDetached() { + return this._detachedScope.isClosed(); + } + onLifecycleEvent(event) { + if (this._firedLifecycleEvents.has(event)) + return; + this._firedLifecycleEvents.add(event); + this.emit(_Frame.Events.AddLifecycle, event); + if (this === this._page.mainFrame() && this._url !== "about:blank") + this.apiLog(` "${event}" event fired`); + this._page.mainFrame()._recalculateNetworkIdle(); + } + _onClearLifecycle() { + for (const event of this._firedLifecycleEvents) + this.emit(_Frame.Events.RemoveLifecycle, event); + this._firedLifecycleEvents.clear(); + this._inflightRequests = new Set(Array.from(this._inflightRequests).filter((request2) => request2 === this._currentDocument.request)); + this._stopNetworkIdleTimer(); + if (this._inflightRequests.size === 0) + this._startNetworkIdleTimer(); + this._page.mainFrame()._recalculateNetworkIdle(this); + this.onLifecycleEvent("commit"); + } + _setPendingDocument(documentInfo) { + this._pendingDocument = documentInfo; + if (documentInfo) + this.invalidateNonStallingEvaluations("Navigation interrupted the evaluation"); + } + pendingDocument() { + return this._pendingDocument; + } + invalidateNonStallingEvaluations(message) { + if (!this._raceAgainstEvaluationStallingEventsPromises.size) + return; + const error = new Error(message); + for (const promise of this._raceAgainstEvaluationStallingEventsPromises) + promise.reject(error); + } + async raceAgainstEvaluationStallingEvents(cb) { + if (this._pendingDocument) + throw new Error("Frame is currently attempting a navigation"); + if (this._page.browserContext.dialogManager.hasOpenDialogsForPage(this._page)) + throw new Error("Open JavaScript dialog prevents evaluation"); + const promise = new ManualPromise(); + this._raceAgainstEvaluationStallingEventsPromises.add(promise); + try { + return await Promise.race([ + cb(), + promise + ]); + } finally { + this._raceAgainstEvaluationStallingEventsPromises.delete(promise); + } + } + nonStallingRawEvaluateInExistingMainContext(expression2) { + return this.raceAgainstEvaluationStallingEvents(() => { + const context2 = this._existingMainContext(); + if (!context2) + throw new Error("Frame does not yet have a main execution context"); + return context2.rawEvaluateJSON(expression2); + }); + } + nonStallingEvaluateInExistingContext(expression2, world) { + return this.raceAgainstEvaluationStallingEvents(() => { + const context2 = this._contextData.get(world)?.context; + if (!context2) + throw new Error("Frame does not yet have the execution context"); + return context2.evaluateExpression(expression2, { isFunction: false }); + }); + } + _recalculateNetworkIdle(frameThatAllowsRemovingNetworkIdle) { + let isNetworkIdle = this._firedNetworkIdleSelf; + for (const child of this._childFrames) { + child._recalculateNetworkIdle(frameThatAllowsRemovingNetworkIdle); + if (!child._firedLifecycleEvents.has("networkidle")) + isNetworkIdle = false; + } + if (isNetworkIdle && !this._firedLifecycleEvents.has("networkidle")) { + this._firedLifecycleEvents.add("networkidle"); + this.emit(_Frame.Events.AddLifecycle, "networkidle"); + if (this === this._page.mainFrame() && this._url !== "about:blank") + this.apiLog(` "networkidle" event fired`); + } + if (frameThatAllowsRemovingNetworkIdle !== this && this._firedLifecycleEvents.has("networkidle") && !isNetworkIdle) { + this._firedLifecycleEvents.delete("networkidle"); + this.emit(_Frame.Events.RemoveLifecycle, "networkidle"); + } + } + async raceNavigationAction(progress2, action) { + progress2.setAllowConcurrentOrNestedRaces(true); + const result2 = await progress2.race(LongStandingScope.raceMultiple([ + this._detachedScope, + this._page.openScope + ], action().catch((e) => { + if (e instanceof NavigationAbortedError && e.documentId) { + const data = this._redirectedNavigations.get(e.documentId); + if (data) { + progress2.log(`waiting for redirected navigation to "${data.url}"`); + return progress2.race(data.gotoPromise); + } + } + throw e; + }))); + progress2.setAllowConcurrentOrNestedRaces(false); + return result2; + } + redirectNavigation(url2, documentId, referer) { + const controller = new ProgressController(); + const data = { + url: url2, + gotoPromise: controller.run((progress2) => this.gotoImpl(progress2, url2, { referer }), 0) + }; + this._redirectedNavigations.set(documentId, data); + data.gotoPromise.finally(() => this._redirectedNavigations.delete(documentId)); + } + async goto(progress2, url2, options = {}) { + const constructedNavigationURL = constructURLBasedOnBaseURL(this._page.browserContext._options.baseURL, url2); + return this.raceNavigationAction(progress2, async () => this.gotoImpl(progress2, constructedNavigationURL, options)); + } + async gotoImpl(progress2, url2, options) { + const waitUntil = verifyLifecycle("waitUntil", options.waitUntil === void 0 ? "load" : options.waitUntil); + progress2.log(`navigating to "${url2}", waiting until "${waitUntil}"`); + const headers = this._page.extraHTTPHeaders() || []; + const refererHeader = headers.find((h) => h.name.toLowerCase() === "referer"); + let referer = refererHeader ? refererHeader.value : void 0; + if (options.referer !== void 0) { + if (referer !== void 0 && referer !== options.referer) + throw new Error('"referer" is already specified as extra HTTP header'); + referer = options.referer; + } + url2 = helper.completeUserURL(url2); + const navigationEvents = []; + const collectNavigations = (arg) => navigationEvents.push(arg); + this.on(_Frame.Events.InternalNavigation, collectNavigations); + let navigateResult; + try { + navigateResult = await progress2.race(this._page.delegate.navigateFrame(this, url2, referer)); + } finally { + this.off(_Frame.Events.InternalNavigation, collectNavigations); + } + let event; + if (navigateResult.newDocumentId) { + const predicate = (event2) => { + return event2.newDocument && (event2.newDocument.documentId === navigateResult.newDocumentId || !event2.error); + }; + const events = navigationEvents.filter(predicate); + if (events.length) + event = events[0]; + else + event = await helper.waitForEvent(progress2, this, _Frame.Events.InternalNavigation, predicate).promise; + if (event.newDocument.documentId !== navigateResult.newDocumentId) { + throw new NavigationAbortedError(navigateResult.newDocumentId, `Navigation to "${url2}" is interrupted by another navigation to "${event.url}"`); + } + if (event.error) + throw event.error; + } else { + const predicate = (e) => !e.newDocument; + const events = navigationEvents.filter(predicate); + if (events.length) + event = events[0]; + else + event = await helper.waitForEvent(progress2, this, _Frame.Events.InternalNavigation, predicate).promise; + } + if (!this._firedLifecycleEvents.has(waitUntil)) + await helper.waitForEvent(progress2, this, _Frame.Events.AddLifecycle, (e) => e === waitUntil).promise; + const request2 = event.newDocument ? event.newDocument.request : void 0; + const response2 = request2 ? await request2._finalRequest().response(progress2) : null; + return response2; + } + async waitForNavigation(progress2, requiresNewDocument, options) { + const waitUntil = verifyLifecycle("waitUntil", options.waitUntil === void 0 ? "load" : options.waitUntil); + progress2.log(`waiting for navigation until "${waitUntil}"`); + const navigationEvent = await helper.waitForEvent(progress2, this, _Frame.Events.InternalNavigation, (event) => { + if (event.error) + return true; + if (requiresNewDocument && !event.newDocument) + return false; + progress2.log(` navigated to "${this._url}"`); + return true; + }).promise; + if (navigationEvent.error) + throw navigationEvent.error; + if (!this._firedLifecycleEvents.has(waitUntil)) + await helper.waitForEvent(progress2, this, _Frame.Events.AddLifecycle, (e) => e === waitUntil).promise; + const request2 = navigationEvent.newDocument ? navigationEvent.newDocument.request : void 0; + return request2 ? request2._finalRequest().response(progress2) : null; + } + async waitForLoadState(progress2, state) { + const waitUntil = verifyLifecycle("state", state); + if (!this._firedLifecycleEvents.has(waitUntil)) + await helper.waitForEvent(progress2, this, _Frame.Events.AddLifecycle, (e) => e === waitUntil).promise; + } + async frameElement(progress2) { + return await progress2.race(this._page.delegate.getFrameElement(this)); + } + context(world) { + if (this._page.delegate.noUtilityWorld?.()) + world = "main"; + return this._contextData.get(world).contextPromise.then((contextOrDestroyedReason) => { + if (contextOrDestroyedReason instanceof ExecutionContext) + return contextOrDestroyedReason; + throw new Error(contextOrDestroyedReason.destroyedReason); + }); + } + mainContext() { + return this.context("main"); + } + _existingMainContext() { + return this._contextData.get("main")?.context || null; + } + utilityContext() { + return this.context("utility"); + } + async evaluateExpression(progress2, expression2, options = {}, arg) { + return await progress2.race(this._evaluateExpression(expression2, options, arg)); + } + async _evaluateExpression(expression2, options = {}, arg) { + const context2 = await this.context(options.world ?? "main"); + const value2 = await context2.evaluateExpression(expression2, options, arg); + return value2; + } + async evaluateExpressionHandle(progress2, expression2, options = {}, arg) { + return await progress2.race(this._evaluateExpressionHandle(expression2, options, arg)); + } + async _evaluateExpressionHandle(expression2, options = {}, arg) { + const context2 = await this.context(options.world ?? "main"); + const value2 = await context2.evaluateExpressionHandle(expression2, options, arg); + return value2; + } + async querySelector(progress2, selector, options) { + this.apiLog(` finding element using the selector "${selector}"`); + return progress2.race(this.selectors.query(selector, options)); + } + async waitForSelector(progress2, selector, performActionPreChecksAndLog, options, scope) { + if (options.visibility) + throw new Error("options.visibility is not supported, did you mean options.state?"); + if (options.waitFor && options.waitFor !== "visible") + throw new Error("options.waitFor is not supported, did you mean options.state?"); + const { state = "visible" } = options; + if (!["attached", "detached", "visible", "hidden"].includes(state)) + throw new Error(`state: expected one of (attached|detached|visible|hidden)`); + if (performActionPreChecksAndLog) + progress2.log(`waiting for ${this._asLocator(selector)}${state === "attached" ? "" : " to be " + state}`); + const promise = this.retryWithProgressAndBackoff(progress2, async (progress3, continuePolling) => { + if (performActionPreChecksAndLog) + await this._page.performActionPreChecks(progress3); + const resolved = await progress3.race(this.selectors.resolveInjectedForSelector(selector, options, scope)); + if (!resolved) { + if (state === "hidden" || state === "detached") + return null; + return continuePolling; + } + const result2 = await progress3.race(resolved.injected.evaluateHandle((injected, { info, root }) => { + if (root && !root.isConnected) + throw injected.createStacklessError("Element is not attached to the DOM"); + const elements = injected.querySelectorAll(info.parsed, root || document); + const element3 = elements[0]; + const visible2 = element3 ? injected.utils.isElementVisible(element3) : false; + let log3 = ""; + if (elements.length > 1) { + if (info.strict) + throw injected.strictModeViolationError(info.parsed, elements); + log3 = ` locator resolved to ${elements.length} elements. Proceeding with the first one: ${injected.previewNode(elements[0])}`; + } else if (element3) { + log3 = ` locator resolved to ${visible2 ? "visible" : "hidden"} ${injected.previewNode(element3)}`; + } + injected.checkDeprecatedSelectorUsage(info.parsed, elements); + return { log: log3, element: element3, visible: visible2, attached: !!element3 }; + }, { info: resolved.info, root: resolved.frame === this ? scope : void 0 })); + const { log: log2, visible, attached } = await progress3.race(result2.evaluate((r) => ({ log: r.log, visible: r.visible, attached: r.attached }))); + if (log2) + progress3.log(log2); + const success = { attached, detached: !attached, visible, hidden: !visible }[state]; + if (!success) { + result2.dispose(); + return continuePolling; + } + if (options.omitReturnValue) { + result2.dispose(); + return null; + } + const element2 = state === "attached" || state === "visible" ? await progress3.race(result2.evaluateHandle((r) => r.element)) : null; + result2.dispose(); + if (!element2) + return null; + if (options.__testHookBeforeAdoptNode) + await progress3.race(options.__testHookBeforeAdoptNode()); + try { + const mainContext = await progress3.race(resolved.frame.mainContext()); + return await progress3.race(element2._adoptTo(mainContext)); + } catch (e) { + return continuePolling; + } + }); + return scope ? scope._context.raceAgainstContextDestroyed(promise) : promise; + } + async dispatchEvent(progress2, selector, type3, eventInit = {}, options, scope) { + await this._callOnElementOnceMatches(progress2, selector, (injectedScript, element2, data) => { + injectedScript.dispatchEvent(element2, data.type, data.eventInit); + }, { type: type3, eventInit }, { mainWorld: true, ...options }, scope); + } + async evalOnSelector(progress2, selector, strict, expression2, isFunction2, arg, scope) { + return progress2.race(this._evalOnSelector(selector, strict, expression2, isFunction2, arg, scope)); + } + async _evalOnSelector(selector, strict, expression2, isFunction2, arg, scope) { + const handle = await this.selectors.query(selector, { strict }, scope); + if (!handle) + throw new Error(`Failed to find element matching selector "${selector}"`); + const result2 = await handle.internalEvaluateExpression(expression2, { isFunction: isFunction2 }, arg); + handle.dispose(); + return result2; + } + async evalOnSelectorAll(progress2, selector, expression2, isFunction2, arg, scope) { + return progress2.race(this._evalOnSelectorAll(selector, expression2, isFunction2, arg, scope)); + } + async _evalOnSelectorAll(selector, expression2, isFunction2, arg, scope) { + const arrayHandle = await this.selectors.queryArrayInMainWorld(selector, scope); + const result2 = await arrayHandle.internalEvaluateExpression(expression2, { isFunction: isFunction2 }, arg); + arrayHandle.dispose(); + return result2; + } + async maskSelectors(selectors, color) { + const context2 = await this.utilityContext(); + const injectedScript = await context2.injectedScript(); + await injectedScript.evaluate((injected, { parsed, color: color2 }) => { + injected.maskSelectors(parsed, color2); + }, { parsed: selectors, color }); + } + async querySelectorAll(progress2, selector) { + return progress2.race(this.selectors.queryAll(selector)); + } + async queryCount(progress2, selector, options) { + try { + return await progress2.race(this.selectors.queryCount(selector, options)); + } catch (e) { + if (this.isNonRetriableError(e)) + throw e; + return 0; + } + } + async content(progress2) { + return progress2.race(this._content()); + } + async _content() { + try { + const context2 = await this.utilityContext(); + return await context2.evaluate(() => { + let retVal = ""; + if (document.doctype) + retVal = new XMLSerializer().serializeToString(document.doctype); + if (document.documentElement) + retVal += document.documentElement.outerHTML; + return retVal; + }); + } catch (e) { + if (this.isNonRetriableError(e)) + throw e; + throw new Error(`Unable to retrieve content because the page is navigating and changing the content.`); + } + } + async setContent(progress2, html, options) { + const tag = `--playwright--set--content--${createGuid()}--`; + await this.raceNavigationAction(progress2, async () => { + const waitUntil = options.waitUntil === void 0 ? "load" : options.waitUntil; + progress2.log(`setting frame content, waiting until "${waitUntil}"`); + const context2 = await progress2.race(this.utilityContext()); + const tagPromise = new ManualPromise(); + this._page.frameManager._consoleMessageTags.set(tag, () => { + this._onClearLifecycle(); + tagPromise.resolve(); + }); + progress2.setAllowConcurrentOrNestedRaces(true); + const lifecyclePromise = progress2.race(tagPromise).then(() => this.waitForLoadState(progress2, waitUntil)); + const contentPromise = progress2.race(context2.evaluate(({ html: html2, tag: tag2 }) => { + document.open(); + console.debug(tag2); + document.write(html2); + document.close(); + }, { html, tag })); + await Promise.all([contentPromise, lifecyclePromise]); + progress2.setAllowConcurrentOrNestedRaces(false); + return null; + }).finally(() => { + this._page.frameManager._consoleMessageTags.delete(tag); + }); + } + name() { + return this._name || ""; + } + url() { + return this._url; + } + origin() { + if (!this._url.startsWith("http")) + return; + return parseURL2(this._url)?.origin; + } + parentFrame() { + return this._parentFrame; + } + _getChildFrames() { + return Array.from(this._childFrames); + } + async addScriptTag(progress2, params2) { + return await progress2.race(this._addScriptTag(params2)); + } + async _addScriptTag(params2) { + const { + url: url2 = null, + content = null, + type: type3 = "" + } = params2; + if (!url2 && !content) + throw new Error("Provide an object with a `url`, `path` or `content` property"); + const context2 = await this.mainContext(); + return this._raceWithCSPError(async () => { + if (url2 !== null) + return (await context2.evaluateHandle(addScriptUrl, { url: url2, type: type3 })).asElement(); + const result2 = (await context2.evaluateHandle(addScriptContent, { content, type: type3 })).asElement(); + if (this._page.delegate.cspErrorsAsynchronousForInlineScripts) + await context2.evaluate(() => true); + return result2; + }); + async function addScriptUrl(params3) { + const script = document.createElement("script"); + script.src = params3.url; + if (params3.type) + script.type = params3.type; + const promise = new Promise((res, rej) => { + script.onload = res; + script.onerror = (e) => rej(typeof e === "string" ? new Error(e) : new Error(`Failed to load script at ${script.src}`)); + }); + document.head.appendChild(script); + await promise; + return script; + } + function addScriptContent(params3) { + const script = document.createElement("script"); + script.type = params3.type || "text/javascript"; + script.text = params3.content; + let error = null; + script.onerror = (e) => error = e; + document.head.appendChild(script); + if (error) + throw error; + return script; + } + } + async addStyleTag(progress2, params2) { + return await progress2.race(this._addStyleTag(params2)); + } + async _addStyleTag(params2) { + const { + url: url2 = null, + content = null + } = params2; + if (!url2 && !content) + throw new Error("Provide an object with a `url`, `path` or `content` property"); + const context2 = await this.mainContext(); + return this._raceWithCSPError(async () => { + if (url2 !== null) + return (await context2.evaluateHandle(addStyleUrl, url2)).asElement(); + return (await context2.evaluateHandle(addStyleContent, content)).asElement(); + }); + async function addStyleUrl(url3) { + const link = document.createElement("link"); + link.rel = "stylesheet"; + link.href = url3; + const promise = new Promise((res, rej) => { + link.onload = res; + link.onerror = rej; + }); + document.head.appendChild(link); + await promise; + return link; + } + async function addStyleContent(content2) { + const style = document.createElement("style"); + style.type = "text/css"; + style.appendChild(document.createTextNode(content2)); + const promise = new Promise((res, rej) => { + style.onload = res; + style.onerror = rej; + }); + document.head.appendChild(style); + await promise; + return style; + } + } + async _raceWithCSPError(func) { + const listeners = []; + let result2; + let error; + let cspMessage; + const actionPromise = func().then((r) => result2 = r).catch((e) => error = e); + const errorPromise = new Promise((resolve) => { + listeners.push(eventsHelper.addEventListener(this._page.browserContext, BrowserContext.Events.Console, (message) => { + if (message.page() !== this._page || message.type() !== "error") + return; + if (message.text().includes("Content-Security-Policy") || message.text().includes("Content Security Policy")) { + cspMessage = message; + resolve(); + } + })); + }); + await Promise.race([actionPromise, errorPromise]); + eventsHelper.removeEventListeners(listeners); + if (cspMessage) + throw new Error(cspMessage.text()); + if (error) + throw error; + return result2; + } + async retryWithProgressAndBackoff(progress2, action) { + const backoffScale = [20, 50, 100, 100, 500]; + if (progress2.timeout) { + while (backoffScale.length && backoffScale[backoffScale.length - 1] > progress2.timeout / 5) + backoffScale.pop(); + } + return await this.retryWithProgressAndTimeouts(progress2, backoffScale, action); + } + async retryWithProgressAndTimeouts(progress2, timeouts, action) { + const continuePolling = Symbol("continuePolling"); + timeouts = [0, ...timeouts]; + let timeoutIndex = 0; + while (true) { + const timeout = timeouts[Math.min(timeoutIndex++, timeouts.length - 1)]; + if (timeout) { + const actionPromise = new Promise((f) => setTimeout(f, timeout)); + await progress2.race(LongStandingScope.raceMultiple([ + this._page.openScope, + this._detachedScope + ], actionPromise)); + } + try { + const result2 = await action(progress2, continuePolling); + if (result2 === continuePolling) + continue; + return result2; + } catch (e) { + if (this.isNonRetriableError(e)) + throw e; + continue; + } + } + } + isNonRetriableError(e) { + if (isAbortError(e)) + return true; + if (isJavaScriptErrorInEvaluate(e) || isSessionClosedError(e)) + return true; + if (isNonRecoverableDOMError(e) || isInvalidSelectorError(e)) + return true; + if (this._isDetached()) + return true; + return false; + } + async _retryWithProgressIfNotConnected(progress2, selector, options, action) { + progress2.log(`waiting for ${this._asLocator(selector)}`); + const noAutoWaiting = options.__testHookNoAutoWaiting ?? options.noAutoWaiting; + const performActionPreChecks = (options.performActionPreChecks ?? !options.force) && !noAutoWaiting; + return this.retryWithProgressAndBackoff(progress2, async (progress3, continuePolling) => { + if (performActionPreChecks) + await this._page.performActionPreChecks(progress3); + const resolved = await progress3.race(this.selectors.resolveInjectedForSelector(selector, { strict: options.strict })); + if (!resolved) { + if (noAutoWaiting) + throw new NonRecoverableDOMError("Element(s) not found"); + return continuePolling; + } + const result2 = await progress3.race(resolved.injected.evaluateHandle((injected, { info }) => { + const elements = injected.querySelectorAll(info.parsed, document); + injected.markTargetElements(new Set(elements)); + const element3 = elements[0]; + let log3 = ""; + if (elements.length > 1) { + if (info.strict) + throw injected.strictModeViolationError(info.parsed, elements); + log3 = ` locator resolved to ${elements.length} elements. Proceeding with the first one: ${injected.previewNode(elements[0])}`; + } else if (element3) { + log3 = ` locator resolved to ${injected.previewNode(element3)}`; + } + injected.checkDeprecatedSelectorUsage(info.parsed, elements); + return { log: log3, success: !!element3, element: element3 }; + }, { info: resolved.info })); + const { log: log2, success } = await progress3.race(result2.evaluate((r) => ({ log: r.log, success: r.success }))); + if (log2) + progress3.log(log2); + if (!success) { + if (noAutoWaiting) + throw new NonRecoverableDOMError("Element(s) not found"); + result2.dispose(); + return continuePolling; + } + const element2 = await progress3.race(result2.evaluateHandle((r) => r.element)); + result2.dispose(); + try { + const result3 = await action(progress3, element2); + if (result3 === "error:notconnected") { + if (noAutoWaiting) + throw new NonRecoverableDOMError("Element is not attached to the DOM"); + progress3.log("element was detached from the DOM, retrying"); + return continuePolling; + } + return result3; + } finally { + element2?.dispose(); + } + }); + } + async rafrafTimeoutScreenshotElementWithProgress(progress2, selector, timeout, options) { + return await this._retryWithProgressIfNotConnected(progress2, selector, { strict: true, performActionPreChecks: true }, async (progress3, handle) => { + await handle._frame.rafrafTimeout(progress3, timeout); + return await this._page.screenshotter.screenshotElement(progress3, handle, options); + }); + } + async click(progress2, selector, options) { + return assertDone(await this._retryWithProgressIfNotConnected(progress2, selector, options, (progress3, handle) => handle._click(progress3, { ...options, waitAfter: !options.noWaitAfter }))); + } + async dblclick(progress2, selector, options) { + return assertDone(await this._retryWithProgressIfNotConnected(progress2, selector, options, (progress3, handle) => handle._dblclick(progress3, options))); + } + async dragAndDrop(progress2, source11, target, options) { + assertDone(await this._retryWithProgressIfNotConnected(progress2, source11, options, async (progress3, handle) => { + return handle._retryPointerAction(progress3, "move and down", false, async (progress4, point) => { + await this._page.mouse.move(progress4, point.x, point.y); + await this._page.mouse.down(progress4); + }, { + ...options, + waitAfter: "disabled", + position: options.sourcePosition + }); + })); + assertDone(await this._retryWithProgressIfNotConnected(progress2, target, { ...options, performActionPreChecks: false }, async (progress3, handle) => { + return handle._retryPointerAction(progress3, "move and up", false, async (progress4, point) => { + await this._page.mouse.move(progress4, point.x, point.y, { steps: options.steps }); + await this._page.mouse.up(progress4); + }, { + ...options, + waitAfter: "disabled", + position: options.targetPosition + }); + })); + } + async tap(progress2, selector, options) { + if (!this._page.browserContext._options.hasTouch) + throw new Error("The page does not support tap. Use hasTouch context option to enable touch support."); + return assertDone(await this._retryWithProgressIfNotConnected(progress2, selector, options, (progress3, handle) => handle._tap(progress3, options))); + } + async fill(progress2, selector, value2, options) { + return assertDone(await this._retryWithProgressIfNotConnected(progress2, selector, options, (progress3, handle) => handle._fill(progress3, value2, options))); + } + async focus(progress2, selector, options) { + assertDone(await this._retryWithProgressIfNotConnected(progress2, selector, options, (progress3, handle) => handle._focus(progress3))); + } + async blur(progress2, selector, options) { + assertDone(await this._retryWithProgressIfNotConnected(progress2, selector, options, (progress3, handle) => handle._blur(progress3))); + } + async resolveSelector(progress2, selector, options = {}) { + const element2 = await progress2.race(this.selectors.query(selector, options)); + if (!element2) + throw new Error(`No element matching ${selector}`); + const generated = await progress2.race(element2.evaluateInUtility(async ([injected, node]) => { + return injected.generateSelectorSimple(node); + }, {})); + if (!generated) + throw new Error(`Unable to generate locator for ${selector}`); + let frame = element2._frame; + const result2 = [generated]; + while (frame?.parentFrame()) { + const frameElement = await frame.frameElement(progress2); + if (frameElement) { + const generated2 = await progress2.race(frameElement.evaluateInUtility(async ([injected, node]) => { + return injected.generateSelectorSimple(node); + }, {})); + frameElement.dispose(); + if (generated2 === "error:notconnected" || !generated2) + throw new Error(`Unable to generate locator for ${selector}`); + result2.push(generated2); + } + frame = frame.parentFrame(); + } + const resolvedSelector = result2.reverse().join(" >> internal:control=enter-frame >> "); + return { resolvedSelector }; + } + async textContent(progress2, selector, options, scope) { + return this._callOnElementOnceMatches(progress2, selector, (injected, element2) => element2.textContent, void 0, options, scope); + } + async innerText(progress2, selector, options, scope) { + return this._callOnElementOnceMatches(progress2, selector, (injectedScript, element2) => { + if (element2.namespaceURI !== "http://www.w3.org/1999/xhtml") + throw injectedScript.createStacklessError("Node is not an HTMLElement"); + return element2.innerText; + }, void 0, options, scope); + } + async innerHTML(progress2, selector, options, scope) { + return this._callOnElementOnceMatches(progress2, selector, (injected, element2) => element2.innerHTML, void 0, options, scope); + } + async getAttribute(progress2, selector, name, options, scope) { + return this._callOnElementOnceMatches(progress2, selector, (injected, element2, data) => element2.getAttribute(data.name), { name }, options, scope); + } + async inputValue(progress2, selector, options, scope) { + return this._callOnElementOnceMatches(progress2, selector, (injectedScript, node) => { + const element2 = injectedScript.retarget(node, "follow-label"); + if (!element2 || element2.nodeName !== "INPUT" && element2.nodeName !== "TEXTAREA" && element2.nodeName !== "SELECT") + throw injectedScript.createStacklessError("Node is not an ,